| 인터넷 초안 | JSON 스키마 | 2022년 6월 |
| Wright 외 | 2022년 12월 18일 만료 | [페이지] |
JSON 스키마는 JSON 데이터의 구조를 설명하기 위한 JSON 기반 형식인 미디어 유형 "application/schema+json"을 정의합니다. JSON 스키마는 JSON 문서가 어떤 모습이어야 하는지, 그로부터 정보를 추출하는 방법, 그리고 그것과 상호작용하는 방법을 단언합니다. "application/schema-instance+json" 미디어 유형은 "application/json" 문서에 제공될 수 있는 것 이상의 기능이 풍부한 "application/schema+json"과의 통합을 제공합니다.¶
이 초안의 이슈 목록은 다음 위치에서 확인할 수 있습니다. https://github.com/json-schema-org/json-schema-spec/issues.¶
추가 정보는 https://json-schema.org/를 참조하십시오.¶
피드백을 제공하려면 이 이슈 트래커, 홈페이지에 나열된 커뮤니케이션 방법, 또는 문서 편집자에게 보내는 이메일을 사용하십시오.¶
이 인터넷 초안은 BCP 78 및 BCP 79의 조항을 완전히 준수하여 제출되었습니다.¶
인터넷 초안은 인터넷 엔지니어링 태스크 포스(IETF)의 작업 문서입니다. 다른 그룹도 작업 문서를 인터넷 초안으로 배포할 수 있음에 유의하십시오. 현재 인터넷 초안 목록은 https://datatracker.ietf.org/drafts/current/에 있습니다.¶
인터넷 초안은 최대 6개월 동안 유효한 초안 문서이며, 언제든지 다른 문서로 갱신, 대체 또는 폐기될 수 있습니다. 인터넷 초안을 참조 자료로 사용하거나 "진행 중인 작업" 이외의 방식으로 인용하는 것은 부적절합니다.¶
이 인터넷 초안은 2022년 12월 18일에 만료됩니다.¶
Copyright (c) 2022 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
JSON 스키마는 JSON 데이터의 구조를 정의하기 위한 JSON 미디어 유형입니다. JSON 스키마는 JSON 데이터의 검증, 문서화, 하이퍼링크 탐색 및 상호작용 제어를 정의하기 위한 것입니다.¶
이 명세는 JSON 스키마의 핵심 용어와 메커니즘을 정의하며, 여기에는 참조로 다른 JSON 스키마를 가리키기, JSON 스키마 참조 역참조하기, 사용 중인 방언 지정하기, 방언의 어휘 요구 사항 지정하기, 그리고 예상 출력을 정의하기가 포함됩니다.¶
다른 명세들은 검증, 연결, 애너테이션, 탐색 및 상호작용에 관한 단언을 수행하는 어휘들을 정의합니다.¶
이 문서에서 핵심 단어 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL"은 RFC 2119 [RFC2119]에 설명된 대로 해석되어야 합니다.¶
이 문서에서 용어 "JSON", "JSON text", "JSON value", "member", "element", "object", "array", "number", "string", "boolean", "true", "false", "null"은 RFC 8259 [RFC8259]에 정의된 대로 해석되어야 합니다.¶
이 문서는 JSON 데이터를 설명하기 위한 JSON 스키마를 식별하기 위해 새 미디어 유형 "application/schema+json"을 제안합니다. 또한 추가 통합 기능을 제공하기 위해, 더 나아가 선택적 미디어 유형인 "application/schema-instance+json"도 제안합니다. JSON 스키마 자체는 JSON 문서입니다. 이 명세와 관련 명세들은 작성자가 JSON 데이터를 여러 방식으로 설명할 수 있게 하는 키워드를 정의합니다.¶
JSON 스키마는 키워드를 사용하여 JSON 인스턴스에 제약을 단언하거나 그러한 인스턴스에 추가 정보를 애너테이션으로 부여합니다. 추가 키워드는 더 복잡한 JSON 데이터 구조에, 또는 어떤 종류의 조건에 기반하여 단언과 애너테이션을 적용하는 데 사용됩니다.¶
재사용을 용이하게 하기 위해, 키워드는 어휘로 구성될 수 있습니다. 어휘는 키워드 목록과 그 구문 및 의미로 이루어집니다. 방언은 메타 스키마에서 식별되는, 어휘들의 집합과 그 필수 지원으로 정의됩니다.¶
JSON 스키마는 추가 어휘를 정의하거나, 또는 덜 형식적으로 어떤 어휘에도 속하지 않는 추가 키워드를 정의하여 확장할 수 있습니다. 인식되지 않은 개별 키워드는 그 값을 애너테이션으로 수집할 뿐이며, 인식되지 않은 어휘에 대한 동작은 어떤 어휘가 사용 중인지 선언할 때 제어할 수 있습니다.¶
이 문서는 모든 구현이 반드시 지원해야 하며 비활성화할 수 없는 핵심 어휘를 정의합니다. 그 키워드들은 각각 필수적 성격을 강조하기 위해 "$" 문자로 접두됩니다. 이 어휘는 "application/schema+json" 미디어 유형의 기능에 필수적이며, 다른 어휘를 로드하는 부트스트랩에 사용됩니다.¶
또한 이 문서는 하위 스키마를 조건부로 적용하고, 객체와 배열의 내용에 하위 스키마를 적용하기 위한 키워드의 RECOMMENDED 어휘를 정의합니다. 이 어휘 또는 이와 매우 유사한 어휘는 단순하지 않은 JSON 인스턴스를 위한 스키마를 작성하는 데 필요하며, 그 스키마가 단언 검증, 애너테이션, 또는 둘 모두를 목적으로 하든 마찬가지입니다. 필수 핵심 어휘의 일부는 아니지만, 최대한의 상호운용성을 위해 이 추가 어휘는 이 문서에 포함되며 그 사용이 강하게 권장됩니다.¶
구조적 검증이나 하이퍼미디어 애너테이션 같은 목적을 위한 추가 어휘들은 다른 문서에서 정의됩니다. 이러한 다른 문서들은 각각 그 문서의 목적에 맞는 스키마를 작성하는 데 필요한 표준 어휘 집합을 모은 방언을 정의합니다.¶
JSON 문서는 application/json 미디어 유형으로 설명되는 정보 리소스 (일련의 옥텟)입니다.¶
JSON 스키마에서는, 이 명세가 정의하는 데이터 모델 때문에 "JSON document", "JSON text", "JSON value"라는 용어가 서로 바꾸어 쓸 수 있습니다.¶
JSON 스키마는 JSON 문서에 대해서만 정의됩니다. 그러나 JSON 스키마 데이터 모델에 따라 파싱되거나 처리될 수 있는 모든 문서 또는 메모리 구조는 CBOR [RFC7049] 같은 미디어 유형을 포함하여 JSON 스키마에 대해 해석될 수 있습니다.¶
스키마가 적용되는 JSON 문서는 "인스턴스"라고 알려져 있습니다.¶
JSON 스키마는 "application/json" 또는 호환 문서, "+json" 구조화 구문 접미사가 있는 미디어 유형을 포함하는 문서에 대해 정의됩니다.¶
이들 중에서, 이 명세는 URI의 프래그먼트 처리를 정의하는 "application/schema-instance+json" 미디어 유형을 정의합니다.¶
JSON 스키마는 데이터 모델에 따라 문서를 해석합니다. 이 데이터 모델에 따라 해석된 JSON 값을 "인스턴스"라고 합니다.¶
인스턴스는 여섯 가지 기본 유형 중 하나를 가지며, 유형에 따라 가능한 값의 범위가 있습니다:¶
따라서 데이터 모델 내에서 같은 수인 숫자의 서로 다른 어휘적 표현을 포함하여 공백과 형식화에 관한 사항은 JSON 스키마의 범위 밖에 있습니다. 이러한 어휘적 표현의 차이를 다루고자 하는 JSON 스키마 어휘 (섹션 8.1)는 원래 JSON 표현 유니코드 문자를 사용할 수 있음에 의존하기보다는 데이터 모델 안에서 형식화된 문자열을 정확히 해석하기 위한 키워드를 정의해야 합니다. ¶
객체는 같은 키를 가진 두 속성을 가질 수 없으므로, 단일 객체 안에서 같은 키를 가진 두 속성을 정의하려는 JSON 문서에 대한 동작은 정의되지 않습니다.¶
JSON 스키마 어휘는 자체 확장 유형 시스템을 자유롭게 정의할 수 있음에 유의하십시오. 이를 여기에서 정의하는 핵심 데이터 모델 유형과 혼동해서는 안 됩니다. 예를 들어 "integer"는 어휘가 키워드의 값으로 정의하기에 합리적인 유형이지만, 데이터 모델은 정수와 다른 숫자 사이를 구별하지 않습니다.¶
두 JSON 인스턴스는 같은 유형이고 데이터 모델에 따라 같은 값을 가질 때, 그리고 그때에만 같다고 합니다. 구체적으로 이는 다음을 의미합니다:¶
이 정의에 함축된 것은 배열은 같은 길이여야 하고, 객체는 같은 수의 멤버를 가져야 하며, 객체의 속성에는 순서가 없고, 같은 키를 가진 여러 속성을 정의할 방법은 없으며, 단순한 형식화 차이(들여쓰기, 쉼표 위치, 뒤따르는 0)는 중요하지 않다는 점입니다.¶
인스턴스가 여섯 가지 JSON 데이터 유형 중 어느 것에도 속하지 않을 수 있는, JSON 스키마 데이터 모델의 상위 집합과 함께 JSON 스키마를 사용할 수 있습니다.¶
이 경우에도 애너테이션은 여전히 적용되지만, 대부분의 검증 키워드는 항상 통과하거나 항상 실패하므로 유용하지 않습니다.¶
사용자 정의 어휘는 핵심 데이터 모델의 상위 집합에 대한 지원을 정의할 수 있습니다. 스키마 자체도 이 상위 집합으로만 표현 가능할 수 있습니다. 예를 들어 "const" 키워드를 사용하기 위해서입니다.¶
JSON 스키마 문서, 또는 간단히 스키마는 인스턴스를 설명하는 데 사용되는 JSON 문서입니다. 스키마 자체도 인스턴스로 해석될 수 있지만, 항상 "application/schema-instance+json"이 아니라 "application/schema+json" 미디어 유형이 부여되어야 합니다. "application/schema+json" 미디어 유형은 "application/schema-instance+json"이 제공하는 프래그먼트 식별자 구문과 의미의 상위 집합을 제공하도록 정의됩니다.¶
JSON 스키마는 객체 또는 불리언이어야 합니다.¶
인스턴스에 적용되는 객체 속성은 키워드, 또는 스키마 키워드라고 합니다. 넓게 말해, 키워드는 다섯 범주 중 하나에 속합니다:¶
키워드는 여러 범주에 속할 수 있지만, 적용자는 하위 스키마의 결과에 기반한 단언 결과만 생성해야 합니다. 하위 스키마와 독립적인 추가 제약을 정의해서는 안 됩니다.¶
같은 스키마 객체 안의 속성인 키워드는 인접 키워드라고 합니다.¶
확장 키워드, 즉 이 문서와 그 동반 문서들 밖에서 정의된 키워드는 다른 동작도 자유롭게 정의할 수 있습니다.¶
JSON 스키마는 스키마 키워드가 아닌 속성을 포함할 수 있습니다. 알 수 없는 키워드는 애너테이션으로 처리해야 하며, 이때 키워드의 값은 애너테이션의 값입니다.¶
빈 스키마는 속성이 없거나 알 수 없는 속성만 있는 JSON 스키마입니다.¶
불리언 스키마 값 "true"와 "false"는 인스턴스 값과 관계없이 항상 자기 자신을 단언 결과로 생성하는 사소한 스키마입니다. 이들은 애너테이션 결과를 생성하지 않습니다.¶
이러한 불리언 스키마는 스키마 작성자의 의도를 명확히 하고 스키마 처리 최적화를 용이하게 하기 위해 존재합니다. 이들은 다음 스키마 객체와 동일하게 동작합니다. 여기서 "not"은 이 문서에서 정의한 하위 스키마 적용 어휘의 일부입니다.¶
빈 스키마 객체는 모호하지 않지만, "false" 스키마에는 가능한 등가 표현이 많이 있습니다. 불리언 값을 사용하면 인간 독자와 구현 모두에게 의도가 명확해집니다.¶
스키마 어휘, 또는 간단히 어휘는 키워드, 그 구문 및 의미의 집합입니다. 어휘는 일반적으로 특정 목적을 중심으로 구성됩니다. 검증, 하이퍼미디어, 또는 사용자 인터페이스 생성과 같은 JSON 스키마의 다양한 사용은 서로 다른 어휘 집합을 포함하게 됩니다.¶
어휘는 JSON 스키마에서 재사용의 기본 단위입니다. 스키마 작성자는 스키마를 처리하기 위해 어떤 어휘가 필수이거나 선택적인지 표시할 수 있기 때문입니다. 어휘는 메타 스키마에서 URI로 식별되므로, 일반 구현은 이전에 알 수 없었던 어휘를 지원하기 위해 확장을 로드할 수 있습니다. 키워드는 어떤 어휘 밖에서도 지원될 수 있지만, 개별 키워드 사용을 표시하는 유사한 메커니즘은 없습니다.¶
스키마 어휘는 대상 독자와 상호운용성 기대에 따라 비공식 설명부터 표준 제안까지 어떤 것으로도 정의될 수 있습니다. 특히 비공개 조직 안에서 어휘 사용을 용이하게 하기 위해, 어휘 명세는 그 사용 범위 밖에 공개될 필요가 없습니다.¶
스키마 자체를 설명하는 스키마를 메타 스키마라고 합니다. 메타 스키마는 JSON 스키마를 검증하고 어떤 어휘를 사용하고 있는지 지정하는 데 사용됩니다.¶
일반적으로 메타 스키마는 어휘 집합을 지정하고, 그 어휘의 구문에 부합하는 스키마를 검증합니다. 그러나 메타 스키마와 어휘는 분리되어 있어, 메타 스키마가 어휘 명세가 요구하는 것보다 더 엄격하거나 더 느슨하게 스키마 적합성을 검증할 수 있습니다. 메타 스키마는 정식 어휘의 일부가 아닌 추가 키워드도 설명하고 검증할 수 있습니다.¶
JSON 스키마 리소스는 정식으로 [RFC6596] 절대 URI [RFC3986]로 식별되는 스키마입니다. 스키마 리소스는 프래그먼트가 있는 URI를 포함한 URI로도 식별될 수 있으며, 그 결과의 보조 리소스( RFC 3986 섹션 3.5 [RFC3986]에 정의됨)가 기본 리소스와 동일한 경우에 그렇습니다. 이는 빈 프래그먼트에서, 또는 한 스키마 리소스가 다른 리소스 안에 내장되어 있을 때 발생할 수 있습니다. 이러한 프래그먼트가 있는 URI는 모두 비정식으로 간주됩니다.¶
루트 스키마는 문제의 전체 JSON 문서를 구성하는 스키마입니다. 루트 스키마는 항상 스키마 리소스이며, 그 URI는 9.1.1절에 설명된 대로 결정됩니다. 다른 형식 안에 스키마를 내장하는 문서는 이 의미에서 루트 스키마 리소스를 가지지 않는다는 점에 유의하십시오. 그러한 사용이 JSON 스키마 문서 및 리소스 개념에 정확히 어떻게 맞는지는 향후 초안에서 명확히 할 것입니다. ¶
일부 키워드는 스키마 자체를 받으며, 이를 통해 JSON 스키마를 중첩할 수 있습니다:¶
{
"title": "root",
"items": {
"title": "array item"
}
}
¶
이 예제 문서에서, 제목이 "array item"인 스키마는 하위 스키마이고, 제목이 "root"인 스키마는 루트 스키마입니다.¶
루트 스키마와 마찬가지로, 하위 스키마는 객체 또는 불리언입니다.¶
8.2.1절에서 논의한 바와 같이, JSON 스키마 문서는 여러 JSON 스키마 리소스를 포함할 수 있습니다. 한정 없이 사용될 때, "루트 스키마"라는 용어는 문서의 루트 스키마를 가리킵니다. 어떤 경우에는 리소스 루트 스키마가 논의됩니다. 리소스의 루트 스키마는 그 최상위 스키마 객체이며, 그 리소스가 독립 JSON 스키마 문서로 추출된다면 문서 루트 스키마도 될 것입니다.¶
여러 스키마 리소스가 내장되어 있든 참조로 연결되어 있든, 그것들은 같은 사용 가능한 동작으로 같은 방식으로 처리됩니다.¶
RFC 6839 [RFC6839]의 3.1절에 따라, 모든 +json 미디어 유형에 지정된 프래그먼트 식별자의 구문과 의미는 "application/json"에 지정된 것과 같아야 합니다. (이 문서의 발행 시점에는 "application/json"에 대해 정의된 프래그먼트 식별 구문이 없습니다.)¶
또한, "application/schema+json" 미디어 유형은 두 가지 프래그먼트 식별자 구조, 즉 일반 이름과 JSON 포인터를 지원합니다. "application/schema-instance+json" 미디어 유형은 하나의 프래그먼트 식별자 구조, 즉 JSON 포인터를 지원합니다.¶
JSON 포인터를 URI 프래그먼트 식별자로 사용하는 방법은 RFC 6901 [RFC6901]에 설명되어 있습니다. 두 가지 프래그먼트 식별자 구문을 지원하는 "application/schema+json"의 경우, 빈 문자열을 포함하여 JSON 포인터 구문과 일치하는 프래그먼트 식별자는 JSON 포인터 프래그먼트 식별자로 해석되어야 합니다.¶
W3C의 프래그먼트 식별자 모범 사례 [W3C.WD-fragid-best-practices-20121025]에 따라, "application/schema+json"의 일반 이름 프래그먼트 식별자는 로컬로 이름이 지정된 스키마를 참조하기 위해 예약됩니다. JSON 포인터 구문과 일치하지 않는 모든 프래그먼트 식별자는 일반 이름 프래그먼트 식별자로 해석되어야 합니다.¶
"application/schema+json" 문서 안에서 일반 이름 프래그먼트 식별자를 정의하고 참조하는 방법은 "$anchor" 키워드 (8.2.2절) 섹션에 지정되어 있습니다.¶
인스턴스는 JSON [RFC8259]에서 정의한 유효한 JSON 값이면 무엇이든 될 수 있습니다. JSON 스키마는 유형에 제한을 두지 않습니다. JSON 스키마는 예를 들어 null을 포함하여 모든 JSON 값을 설명할 수 있습니다.¶
JSON 스키마는 프로그래밍 언어에 구애받지 않으며, 데이터 모델에 설명된 값의 전체 범위를 지원합니다. 그러나 일부 언어와 JSON 파서는 JSON으로 설명 가능한 값의 전체 범위를 메모리 안에서 표현하지 못할 수 있음에 유의하십시오.¶
일부 프로그래밍 언어와 파서는 부동소수점 수에 대해 정수와 다른 내부 표현을 사용합니다.¶
일관성을 위해 정수 JSON 숫자는 소수 부분을 포함하여 인코딩하지 않는 것이 좋습니다.¶
키워드는 제약을 표현하거나 인스턴스 값을 정규 표현식으로 제한하기 위해 정규 표현식을 사용할 수 있습니다. 이러한 정규 표현식은 ECMA-262, 21.2.1절 [ecma262]에 설명된 정규 표현식 방언에 따라 유효해야 합니다.¶
정규 표현식은 유니코드 지원을 제공하기 위해 "u" 플래그(또는 동등한 것)로 작성되어야 하며, 또는 ECMA-262에 정의된 대로 유니코드 지원을 제공하는 방식으로 처리되어야 합니다.¶
또한 정규 표현식 구문 지원의 큰 차이를 고려할 때, 스키마 작성자는 다음 정규 표현식 토큰으로 제한하는 것이 좋습니다:¶
마지막으로, 구현은 정규 표현식을 시작이나 끝 어느 쪽에도 고정된 것으로 간주해서는 안 됩니다. 이는 예를 들어 패턴 "es"가 "expression"과 일치한다는 뜻입니다.¶
추가 스키마 키워드와 스키마 어휘는 어떤 주체에 의해서도 정의될 수 있습니다. 명시적 합의가 없는 한, 스키마 작성자는 이러한 추가 키워드와 어휘가 해당 지원을 명시적으로 문서화하지 않은 구현에서 지원될 것이라고 기대해서는 안 됩니다. 구현은 지원하지 않는 키워드를 애너테이션으로 처리해야 하며, 이때 키워드의 값은 애너테이션의 값입니다.¶
구현은 직접 지원하지 않는 어휘에 대한 처리기를 등록하거나 로드하는 기능을 제공할 수 있습니다. 이러한 처리기를 등록하고 구현하는 정확한 메커니즘은 구현에 따라 달라집니다.¶
JSON 스키마 키워드는 여러 일반 동작 범주에 속합니다. 단언은 인스턴스가 제약을 만족하는지 검증하여 불리언 결과를 생성합니다. 애너테이션은 애플리케이션이 적절하다고 보는 방식으로 사용할 수 있는 정보를 첨부합니다. 적용자는 인스턴스의 일부에 하위 스키마를 적용하고 그 결과를 결합합니다.¶
확장 키워드는 이러한 범주 안에 머무르는 것이 좋으며, 특히 애너테이션이 매우 유연하다는 점을 염두에 두어야 합니다. 복잡한 동작은 보통 스키마 키워드로 직접 구현하기보다 애너테이션 데이터를 기반으로 애플리케이션에 위임하는 편이 더 좋습니다. 그러나 확장 키워드는 특수한 목적을 위해 다른 동작을 정의할 수 있습니다.¶
스키마에 대해 인스턴스를 평가하는 것은 스키마의 모든 키워드를 인스턴스 안의 적절한 위치에 대해 처리하는 것을 포함합니다. 일반적으로 적용자 키워드는 적용자(따라서 하위 스키마)가 없는 스키마 객체에 도달할 때까지 처리됩니다. 인스턴스 안의 적절한 위치는 스키마 객체 안의 단언 및 애너테이션 키워드에 대해 평가되고, 그 결과는 적용자의 규칙에 따라 상위 스키마로 수집됩니다.¶
상위 스키마 객체의 평가는 모든 하위 스키마가 평가된 뒤 완료될 수 있지만, 일부 상황에서는 단언 결과로 인해 평가가 단락될 수 있습니다. 애너테이션을 수집하는 경우, 애너테이션 수집을 위해 전체 단언 결과를 더 이상 변경할 수 없는 하위 스키마를 포함하여 모든 하위 스키마를 검사해야 하므로 일부 단언 결과 단락은 불가능합니다.¶
대부분의 JSON 스키마 키워드는 그 자체로 평가될 수 있거나, 많아야 같은 스키마 객체 안의 인접 키워드 값이나 결과를 고려하면 되지만, 몇몇 키워드는 더 복잡한 동작을 가집니다.¶
키워드의 어휘적 범위는 객체와 배열의 중첩된 JSON 데이터 구조에 의해 결정됩니다. 이러한 범위 중 가장 큰 것은 전체 스키마 문서입니다. 가장 작은 범위는 하위 스키마가 없는 단일 스키마 객체입니다.¶
키워드는 URI-reference 같은 부분 값을 사용하여 정의될 수 있으며, 이는 JSON 문서의 어휘적 구조를 통해 발견되는 다른 URI-reference나 전체 URI 같은 다른 값에 대해 해석되어야 합니다. "$id", "$ref", "$dynamicRef" 핵심 키워드와 "base" JSON Hyper-Schema 키워드는 이러한 종류의 동작의 예입니다.¶
"$schema" 같은 일부 키워드는 전체 스키마 리소스의 어휘적 범위에 적용되므로, 반드시 스키마 리소스의 루트 스키마에만 나타나야 합니다.¶
다른 키워드는 스키마 평가 중에 존재하는 동적 범위를 고려할 수 있으며, 보통 인스턴스 문서와 함께 이루어집니다. 가장 바깥쪽 동적 범위는 처리가 시작되는 스키마 객체이며, 그것이 스키마 리소스 루트가 아니어도 마찬가지입니다. 이 루트 스키마에서 특정 키워드까지의 경로(해결되었을 수 있는 "$ref"와 "$dynamicRef" 키워드를 모두 포함)는 그 키워드의 "검증 경로"로 간주됩니다.¶
참조 키워드를 만날 때까지 어휘적 범위와 동적 범위는 일치합니다. 참조 키워드를 따라가면 처리가 한 어휘적 범위에서 다른 범위로 이동하지만, 동적 범위의 관점에서 참조를 따라가는 것은 값으로 존재하는 하위 스키마로 내려가는 것과 다르지 않습니다. 해당 참조의 반대편에 있는 키워드가 동적 범위를 통해 정보를 해석할 때는, 로컬의 어휘적으로 감싸는 부모를 검사하기보다 참조의 출발 쪽을 자신의 동적 부모로 간주합니다.¶
동적 범위 개념은 주로 "$dynamicRef" 및 "$dynamicAnchor"와 함께 사용되며, 고급 기능으로 간주하고 추가 키워드를 정의할 때 주의해서 사용해야 합니다. 또한 오류와 수집된 애너테이션을 보고할 때도 나타납니다. 같은 어휘적 범위를 서로 다른 동적 범위로 반복해서 다시 방문할 수 있기 때문입니다. 이러한 경우 오류나 애너테이션을 만든 동적 경로를 사용자에게 알리는 것이 중요합니다.¶
키워드 동작은 하위 스키마 (4.3.5절)의 애너테이션 결과 및/또는 인접 키워드 (같은 스키마 객체 안의 키워드)와 그 하위 스키마의 애너테이션 결과를 기준으로 정의될 수 있습니다. 이러한 키워드는 순환 의존성을 만들어서는 안 됩니다. 키워드는 같은 스키마 객체 (4.3절) 안의 다른 키워드가 존재하는지 여부에 따라 자신의 동작을 수정할 수 있습니다.¶
누락된 키워드는 false 단언 결과를 생성해서는 안 되고, 애너테이션 결과를 생성해서도 안 되며, 자신의 동작 정의의 일부로 다른 스키마가 평가되도록 해서도 안 됩니다. 그러나 누락된 키워드는 애너테이션을 제공하지 않으므로, 애너테이션 결과의 부재가 다른 키워드의 동작을 간접적으로 바꿀 수 있습니다.¶
어떤 경우에는 키워드의 누락 시 단언 동작이 특정 값이 생성하는 동작과 동일하며, 키워드 정의는 그러한 값이 알려져 있다면 이를 명시해야 합니다. 그러나 기본 동작을 생성하는 값이 존재할 때 애너테이션 결과를 생성하더라도, 기본 동작은 여전히 애너테이션을 결과로 만들어서는 안 됩니다.¶
애너테이션 수집은 계산과 메모리 양쪽 모두에서 상당한 비용을 추가할 수 있으므로, 구현은 이 기능을 선택적으로 사용하지 않을 수 있습니다. 수집된 애너테이션을 기준으로 지정된 키워드는 적절한 경우 합리적인 대체 접근 방식을 설명해야 합니다. 이 접근 방식은 이 문서의 "items" 및 "additionalProperties" 키워드에서 시연됩니다.¶
이러한 대체 접근 방식이 키워드에 대해 불가능한 경우, 애너테이션 수집을 지원하지 않는 구현은 해당 키워드나 이를 포함하는 어휘를 지원할 수 없다는 점에 유의하십시오.¶
식별자는 스키마의 URI를 정의하거나, 이러한 URI가 참조 (8.2.3절)에서 해석되는 방식에 영향을 주거나, 또는 둘 다를 수행합니다. 이 문서에서 정의한 핵심 어휘는 여러 식별 키워드를 정의하며, 가장 대표적인 것은 "$id"입니다.¶
정식 스키마 URI는 인스턴스를 처리하는 동안 변경되어서는 안 되지만, URI-reference 해석에 영향을 주는 키워드는 런타임에야 완전히 결정되는 동작을 가질 수 있습니다.¶
사용자 정의 식별자 키워드는 가능하지만, 어휘 설계자는 핵심 키워드의 기능을 방해하지 않도록 주의해야 합니다. 예를 들어, 이 명세의 "$dynamicAnchor" 키워드는 자신의 URI 해석 효과를 일치하는 "$dynamicRef" 키워드로 제한하여, "$ref"의 동작은 방해받지 않도록 둡니다.¶
적용자는 단일 스키마 객체로 달성할 수 있는 것보다 더 복잡한 스키마를 만들 수 있게 합니다. 스키마 문서 (4.3절)에 대해 인스턴스를 평가하는 것은 완전한 인스턴스 문서에 루트 스키마 (4.3.5절)를 적용하는 것으로 시작됩니다. 그 후, 적용자라고 알려진 키워드가 어떤 추가 스키마가 적용되는지를 결정하는 데 사용됩니다. 이러한 스키마는 현재 위치에 제자리로 적용될 수도 있고, 자식 위치에 적용될 수도 있습니다.¶
적용될 스키마는 키워드 값의 전부 또는 일부를 이루는 하위 스키마로 존재할 수 있습니다. 또는 적용자가 같은 스키마 문서 안의 다른 위치나 다른 문서 안의 스키마를 참조할 수 있습니다. 그러한 참조된 스키마를 식별하는 메커니즘은 해당 키워드가 정의합니다.¶
적용자 키워드는 또한 하위 스키마 또는 참조된 스키마의 불리언 단언 (7.6절) 결과가 적용자의 불리언 결과를 생성하기 위해 어떻게 수정 및/또는 결합되는지도 정의합니다. 적용자는 하위 스키마의 단언 결과에 어떤 불리언 논리 연산도 적용할 수 있지만, 자신만의 새로운 단언 조건을 도입해서는 안 됩니다.¶
애너테이션 (7.7절) 결과는 인스턴스 위치와 스키마 키워드의 위치와 함께 보존되어, 애플리케이션이 여러 값을 어떻게 해석할지 결정할 수 있게 합니다.¶
7.5절에서 언급했듯이, 적용자 키워드는 적용자의 값 안에 하위 스키마로 포함하는 대신, 적용할 스키마를 참조할 수 있습니다. 이러한 상황에서 적용되는 스키마는 참조되는 스키마라고 하며, 적용자 키워드를 포함하는 스키마는 참조하는 스키마입니다.¶
루트 스키마와 하위 스키마는 스키마 문서 안의 스키마 위치를 기반으로 하는 정적 개념이지만, 참조되는 스키마와 참조하는 스키마는 동적입니다. 인스턴스를 스키마에 대해 평가하는 동안 서로 다른 스키마 쌍은 다양한 참조되는/참조하는 배열에 놓일 수 있습니다.¶
"$ref" (8.2.3.1절) 같은 일부 참조 기반 적용자의 경우, 참조되는 스키마는 스키마 문서의 어휘적 범위를 정적 분석하여 결정할 수 있습니다. "$dynamicRef"("$dynamicAnchor"와 함께) 같은 다른 것들은 동적 범위를 사용할 수 있으므로, 인스턴스와 함께 스키마를 평가하는 과정에서만 해석될 수 있습니다.¶
JSON 스키마는 JSON 문서에 대한 제약을 단언하는 데 사용할 수 있으며, 문서는 그 단언을 통과하거나 실패합니다. 이 접근 방식은 제약에 대한 적합성을 검증하거나, 제약을 만족하기 위해 필요한 것을 문서화하는 데 사용할 수 있습니다.¶
JSON 스키마 구현은 스키마 단언에 대해 인스턴스를 평가할 때 단일 불리언 결과를 생성합니다.¶
인스턴스는 스키마 안에 존재하는 단언에 대해서만 실패할 수 있습니다.¶
대부분의 단언은 특정 기본 유형 안의 값만 제한합니다. 인스턴스의 유형이 해당 키워드가 대상으로 삼는 유형이 아닐 때, 그 인스턴스는 단언을 준수하는 것으로 간주됩니다.¶
예를 들어, 동반 검증 어휘 [json-schema-validation]의 "maxLength" 키워드는: 특정 문자열 (너무 긴 문자열)만 유효하지 않도록 제한합니다. 인스턴스가 숫자, 불리언, null, 배열 또는 객체라면 이 단언에 대해 유효합니다.¶
이 동작은 여러 기본 유형 중 하나일 수 있는 인스턴스에 키워드를 더 쉽게 사용할 수 있게 합니다. 동반 검증 어휘에는 인스턴스를 하나 이상의 기본 유형으로 독립적으로 제한할 수 있는 "type" 키워드도 포함되어 있습니다. 이를 통해 특정 길이의 문자열 또는 null 값을 반환할 수 있는 함수 같은 사용 사례를 간결하게 표현할 수 있습니다:¶
{
"type": ["string", "null"],
"maxLength": 255
}
¶
만약 "maxLength"가 인스턴스 유형도 문자열로 제한했다면, 작성된 예제는 실제로 null 값을 허용하지 않기 때문에 이를 표현하기가 훨씬 더 번거로웠을 것입니다. 명시적으로 달리 지정되지 않는 한 각 키워드는 별도로 평가되므로, "maxLength"가 인스턴스를 문자열로 제한한다면 "type"에 "null"을 포함해도 유용한 효과가 없을 것입니다.¶
JSON 스키마는 인스턴스가 애너테이션을 포함하는 스키마 객체와 그 모든 상위 스키마 객체에 대해 검증될 때마다, 인스턴스에 정보를 애너테이션으로 부여할 수 있습니다. 그 정보는 단순 값일 수도 있고, 인스턴스 내용에 기반하여 계산될 수도 있습니다.¶
애너테이션은 인스턴스 안의 특정 위치에 첨부됩니다. 많은 하위 스키마가 단일 위치에 적용될 수 있으므로, 애플리케이션은 서로 다른 스키마 객체 안의 같은 스키마 키워드가 같은 인스턴스 위치에 첨부한 서로 다른 애너테이션 값을 어떻게 처리할지 결정해야 할 수 있습니다.¶
단언 결과와 달리 애너테이션 데이터는 매우 다양한 형태를 취할 수 있으며, 애플리케이션이 적절하다고 보는 방식으로 사용하도록 제공됩니다. JSON 스키마 구현은 애플리케이션을 대신하여 수집된 정보를 사용할 것으로 기대되지 않습니다.¶
달리 지정되지 않는 한, 애너테이션 키워드의 값은 그 키워드의 값입니다. 그러나 다른 동작도 가능합니다. 예를 들어, JSON Hyper-Schema의 [json-hyper-schema] "links" 키워드는 부분적으로 인스턴스 데이터에 기반하여 값을 생성하는 복합 애너테이션입니다.¶
단언에는 "단락" 평가가 가능하지만, 애너테이션을 수집하려면 전체 단언 결과를 변경할 수 없더라도 인스턴스 위치에 적용되는 모든 스키마를 검사해야 합니다. 유일한 예외는 검증에 실패한 스키마 객체의 하위 스키마를 건너뛸 수 있다는 점입니다. 실패한 스키마의 애너테이션은 보존되지 않기 때문입니다.¶
애너테이션은 애너테이션 수집 동작을 명시적으로 정의하는 키워드에 의해 수집됩니다. 불리언 스키마는 키워드를 사용하지 않으므로 애너테이션을 생성할 수 없음에 유의하십시오.¶
수집된 애너테이션은 다음 정보를 포함해야 합니다:¶
애플리케이션은 값을 제공한 스키마 위치를 기준으로 여러 애너테이션 값 중 어느 것을 사용할지 결정할 수 있습니다. 이는 유연한 사용을 허용하기 위한 것입니다. 스키마 위치를 수집하면 이러한 사용이 용이해집니다.¶
예를 들어, 검증 명세 [json-schema-validation]의 애너테이션과 단언을 사용하는 이 스키마를 생각해 보십시오:¶
명확성을 위해 일부 줄이 줄바꿈되었음에 유의하십시오.¶
{
"title": "Feature list",
"type": "array",
"prefixItems": [
{
"title": "Feature A",
"properties": {
"enabled": {
"$ref": "#/$defs/enabledToggle",
"default": true
}
}
},
{
"title": "Feature B",
"properties": {
"enabled": {
"description": "If set to null, Feature B
inherits the enabled
value from Feature A",
"$ref": "#/$defs/enabledToggle"
}
}
}
],
"$defs": {
"enabledToggle": {
"title": "Enabled",
"description": "Whether the feature is enabled (true),
disabled (false), or under
automatic control (null)",
"type": ["boolean", "null"],
"default": null
}
}
}
¶
이 예에서 Feature A와 Feature B는 모두 재사용 가능한 "enabledToggle" 스키마를 사용합니다. 그 스키마는 "title", "description", "default" 애너테이션을 사용합니다. 따라서 애플리케이션은 Feature A의 추가 "default" 값과 Feature B의 추가 "description" 값을 어떻게 처리할지 결정해야 합니다.¶
애플리케이션 프로그래머와 스키마 작성자는 그 사용 방식에 대해 합의해야 합니다. 이 예에서는 가장 구체적인 "default" 값이 사용되고, 추가적인 더 일반적인 "default" 값은 조용히 무시된다고 합의했다고 가정해 보겠습니다. 또한 모든 "description" 텍스트는 가장 일반적인 것부터 시작해서 가장 구체적인 것으로 끝나도록 사용된다고 합의했다고 가정해 보겠습니다. 이를 위해 스키마 작성자는 이러한 방식으로 결합될 때 작동하는 설명을 작성해야 합니다.¶
애플리케이션은 스키마 위치 경로를 사용하여 어떤 값이 무엇인지 결정할 수 있습니다. 기능의 직접적인 "enabled" 속성 스키마 안의 값은 더 구체적인 반면, "$ref"로 참조되는 재사용 가능한 스키마 아래의 값은 더 일반적입니다. 스키마 위치 경로는 각 값이 "$ref"를 건너 발견되었는지 여부를 보여줍니다.¶
따라서 Feature A는 기본값 true를 사용하고, Feature B는 일반 기본값 null을 사용합니다. Feature A에는 "enabledToggle" 스키마의 일반 설명만 있지만, Feature B는 그 설명을 사용하고, null 값을 해석하는 방법을 설명하는 로컬로 정의된 설명도 덧붙입니다.¶
다른 애플리케이션이 취할 수 있는 다른 합리적인 접근 방식도 있음에 유의하십시오. 예를 들어, 애플리케이션은 스키마 위치와 관계없이 "default"에 대해 서로 다른 두 값이 존재하는 것을 오류로 간주할 수 있습니다.¶
false 단언 결과를 생성하는 스키마 객체는 자체 키워드에서든 하위 스키마의 키워드에서든 어떤 애너테이션 결과도 생성해서는 안 됩니다.¶
전체 스키마 결과에는 다른 스키마 위치에서 수집된 애너테이션이 여전히 포함될 수 있음에 유의하십시오. 다음 스키마가 주어졌다고 합시다:¶
{
"oneOf": [
{
"title": "Integer Value",
"type": "integer"
},
{
"title": "String Value",
"type": "string"
}
]
}
¶
인스턴스 "This is a string"에 대해,
해당 스키마 객체의 type 단언이 실패하므로
제목 애너테이션 "Integer Value"는 폐기됩니다. 인스턴스가
string type 단언을 통과하므로 제목 애너테이션 "String Value"는
유지됩니다.¶
자체 애너테이션 결과를 정의할 가능성 외에도, 적용자 키워드는 자신의 하위 스키마 또는 참조된 스키마에서 수집된 애너테이션을 집계합니다.¶
네 번째 키워드 범주는 스키마 작성자가 관심을 가지는 재사용 가능한 구성 요소나, 재사용에는 적합하지 않은 데이터를 담기 위한 위치를 단순히 예약합니다. 이러한 키워드는 검증 또는 애너테이션 결과에 영향을 주지 않습니다. 핵심 어휘에서 이들의 목적은 특정 목적을 위한 위치가 사용 가능하며 확장 키워드에 의해 재정의되지 않도록 보장하는 것입니다.¶
이러한 키워드가 결과에 직접 영향을 주지는 않지만, 9.4.2절에서 설명하듯이 재사용 가능한 스키마를 위한 위치를 예약하는 인식되지 않은 확장 키워드는 특정 상황에서 참조와 바람직하지 않은 상호작용을 할 수 있습니다.¶
이 문서나 관련 문서의 일부로 정의된 어휘 중에는 인스턴스 데이터를 대상으로 삼거나 로드할 수 있는 키워드를 정의하는 것은 없지만, 다른 어휘가 그렇게 하기를 원할 수 있습니다.¶
키워드는 현재 평가 위치 밖의 인스턴스 일부를 검사하기 위해 JSON 포인터 또는 상대 JSON 포인터를 사용하도록 정의될 수 있습니다.¶
상대 JSON 포인터를 사용하여 위치를 조정할 수 있게 하는 키워드는 기본값이 바람직한 경우 현재 위치를 사용하도록 기본 설정해야 합니다.¶
이 섹션에서 선언되고 모두 "$"로 시작하는 키워드들은 JSON 스키마 핵심 어휘를 구성합니다. 이러한 키워드는 여러 문서에 걸쳐 분할된 스키마나 메타 스키마를 포함하여 어떤 스키마나 메타 스키마를 처리하기 위해 필요하거나, 보장된 상호운용성이 필요한 목적을 위해 키워드를 예약하기 위해 존재합니다.¶
핵심 어휘는 추가 어휘의 처리를 부트스트랩하기 위해 항상 필수로 간주되어야 합니다. 사용 중인 어휘를 선언하기 위해 "$vocabulary" (8.1절) 키워드를 사용하는 메타 스키마는 반드시 핵심 어휘를 명시적으로 나열해야 하며, 이는 필수임을 나타내는 true 값을 가져야 합니다.¶
이 어휘(그리고 이 어휘에 한해서)에 대한 false 값의 동작은 정의되지 않았으며, "$vocabulary"가 존재하지만 핵심 어휘가 포함되지 않은 경우의 동작도 정의되지 않았습니다. 그러나 구현은 이러한 경우를 감지하여 발생 시 오류를 일으키는 것이 권장됩니다. 메타 스키마가 Core를 선택적으로 사용한다고 선언하는 것은 의미가 없습니다.¶
"$vocabulary"를 사용하지 않는 메타 스키마는 그 URI가 true 값과 함께 존재하는 것처럼 핵심 어휘를 요구하는 것으로 간주되어야 합니다.¶
핵심 어휘의 현재 URI는 다음과 같습니다: <https://json-schema.org/draft/2020-12/vocab/core>.¶
대응하는 메타 스키마의 현재 URI는 다음과 같습니다: https://json-schema.org/draft/2020-12/meta/core.¶
"$" 접두사가 핵심 어휘를 위해 공식적으로 예약된 것은 아니지만, 확장 키워드(어휘 안이든 아니든)는 향후 충돌 가능성을 피하기 위해 "$"가 아닌 문자로 시작하는 것이 권장됩니다.¶
메타 스키마와 어휘라는 두 개념은 구현에 스키마를 해석하는 방법을 알려주는 데 사용됩니다. 모든 스키마에는 메타 스키마가 있으며, 이는 "$schema" 키워드를 사용하여 선언할 수 있습니다.¶
메타 스키마는 두 가지 목적을 수행합니다:¶
메타 스키마는 어휘와 분리되어 있어, 어휘를 서로 다른 방식으로 결합할 수 있고, 메타 스키마 작성자는 특정 키워드를 금지하거나 개발 및 테스트 주기 중에 수행할 수 있는 비정상적으로 엄격한 구문 검증 같은 추가 제약을 부과할 수 있습니다. 각 어휘는 일반적으로 그 어휘의 키워드만으로 구성된 메타 스키마를 식별합니다.¶
메타 스키마 작성은 JSON 스키마의 고급 사용이므로, 메타 스키마 기능의 설계는 단순성보다 유연성을 강조합니다.¶
"$schema" 키워드는 JSON 스키마 방언 식별자로도 사용되고, 이 특정 방언을 위해 작성된 유효한 스키마 집합을 설명하는 JSON 스키마 자체인 리소스의 식별자로도 사용됩니다.¶
이 키워드의 값은 URI [RFC3986] (스킴을 포함)이어야 하며, 이 URI는 정규화되어야 합니다. 현재 스키마는 이 URI가 식별하는 메타 스키마에 대해 유효해야 합니다.¶
이 URI가 검색 가능한 리소스를 식별한다면, 그 리소스는 "application/schema+json" 미디어 유형이어야 합니다.¶
"$schema" 키워드는 문서 루트 스키마 객체에서 사용하는 것이 좋으며, 내장된 스키마 리소스의 루트 스키마 객체에서도 사용할 수 있습니다. 리소스가 아닌 루트 스키마 객체에는 나타나서는 안 됩니다. 문서 루트 스키마에 없으면, 그 결과 동작은 구현 정의입니다.¶
이 속성의 값은 이 문서와 다른 문서, 그리고 다른 당사자에 의해 다른 곳에서 정의됩니다.¶
"$vocabulary" 키워드는 메타 스키마에서 사용되어, 해당 메타 스키마가 설명하는 스키마에서 사용할 수 있는 어휘를 식별합니다. 또한 각 어휘가 필수인지 선택적인지를 나타내는 데도 사용되며, 이는 구현이 스키마를 성공적으로 처리하기 위해 필수 어휘를 이해해야 한다는 의미입니다. 이 정보가 함께 방언을 구성합니다. 구현이 이해하는 모든 어휘는 그 어휘 안에 포함된 의미 정의와 일관된 방식으로 처리되어야 합니다.¶
이 키워드의 값은 객체여야 합니다. 객체의 속성 이름은 URI(스킴 포함)여야 하며, 이 URI는 정규화되어야 합니다. 속성 이름으로 나타나는 각 URI는 특정 키워드 집합과 그 의미를 식별합니다.¶
URI는 URL일 수 있지만, 검색 가능한 리소스의 성격은 현재 정의되지 않았으며 향후 사용을 위해 예약되어 있습니다. 어휘 작성자는 text/html 또는 text/plain 같은 사람이 읽을 수 있는 미디어 유형의 어휘 명세 URL을 어휘 URI로 사용할 수 있습니다. 어휘 문서는 향후 초안에 추가될 수 있습니다. 현재로서는 키워드 집합을 식별하는 것으로 충분하다고 간주됩니다. 이는 메타 스키마 검증과 함께 현재의 "vocabularies"가 오늘날 작동하는 방식이기 때문입니다. 향후 어휘 문서 형식은 JSON 문서로 지정될 것이므로, 그동안 text/html 또는 기타 비 JSON 형식을 사용해도 향후 모호성을 만들지 않습니다. ¶
객체 속성의 값은 불리언이어야 합니다. 값이 true이면, 해당 어휘를 인식하지 못하는 구현은 이 메타 스키마를 "$schema"로 선언한 모든 스키마의 처리를 거부해야 합니다. 값이 false이면, 해당 어휘를 인식하지 못하는 구현도 그러한 스키마의 처리를 계속하는 것이 좋습니다. 구현이 그 어휘를 이해한다면 이 값은 영향을 주지 않습니다.¶
6.5에 따라, 인식되지 않은 키워드는 애너테이션으로 처리하는 것이 좋습니다. 인식되지 않은 어휘에 의해 정의된 키워드에 대해서도 이는 그대로 적용됩니다. 현재는 어휘 안에서 정의된 인식되지 않은 키워드와 어떤 어휘에도 속하지 않는 인식되지 않은 키워드를 구별할 수 없습니다.¶
"$vocabulary" 키워드는 메타 스키마로 사용될 의도의 모든 스키마 문서의 루트 스키마에서 사용하는 것이 좋습니다. 하위 스키마에는 나타나서는 안 됩니다.¶
"$vocabulary" 키워드는 메타 스키마로 처리되지 않는 스키마 문서에서는 무시되어야 합니다. 이를 통해 검증기가 M이 선언한 어휘를 이해할 필요 없이, 메타 스키마 M을 그 자체의 메타 스키마 M'에 대해 검증할 수 있습니다.¶
"$vocabulary"가 없으면, 구현은 참조하는 스키마의 "$schema" 키워드의 URI 값에서 메타 스키마를 인식하는 경우 그 메타 스키마에 기반하여 동작을 결정할 수 있습니다. 이는 어휘가 존재하기 전부터 동작(예: Hyper-Schema 사용)이 인식되어 온 방식입니다.¶
스키마가 참조한 메타 스키마가 인식되지 않거나 누락된 경우, 동작은 구현 정의입니다. 구현이 스키마 처리를 계속한다면, 핵심 어휘의 사용을 가정해야 합니다. 구현이 특정 목적을 위해 만들어졌다면, 그 목적에 가장 관련된 모든 어휘의 사용을 가정하는 것이 좋습니다.¶
예를 들어, 검증기인 구현은 이 명세와 동반 검증 명세에 있는 모든 어휘의 사용을 가정해야 합니다.¶
"$vocabulary"에 대한 처리 제한은 "$ref" 또는 유사 키워드를 사용하여 다른 메타 스키마를 참조하는 메타 스키마가 그 다른 메타 스키마의 어휘 선언을 자동으로 상속하지 않는다는 의미임에 유의하십시오. 이러한 모든 선언은 메타 스키마로 사용될 의도의 각 스키마 문서의 루트에 반복되어야 합니다. 이는 예제 메타 스키마 (부록 D.2)에서 시연됩니다. 이 요구 사항은 구현이 각 메타 스키마에 대한 모든 어휘 요구 정보를 한곳에서 찾을 수 있게 합니다. 스키마 확장성은 더 세분화된 메타 스키마를 참조로 결합하는 잠재적인 방법이 끝없이 있음을 의미하므로, 구현이 모든 가능성을 예상하고 참조된 메타 스키마에서 어휘를 검색하도록 요구하는 것은 지나치게 부담스럽습니다. ¶
오류를 수정하기 위해 명세 초안 사이에 갱신된 어휘 및 메타 스키마 URI가 발행될 수 있습니다. 구현은 이 명세 초안 이후이며 다음 초안 이전의 날짜가 붙은 URI를 여기에 나열된 것과 동일한 구문과 의미를 나타내는 것으로 간주해야 합니다.¶
방대한 생태계 안에서 스키마를 구별하기 위해, 스키마는 URI [RFC3986]로 식별되며, 다른 스키마의 URI를 지정하여 그 스키마에 대한 참조를 포함할 수 있습니다.¶
여러 키워드는 상대 URI-reference [RFC3986]나 상대 URI-reference를 구성하는 데 사용되는 값을 받을 수 있습니다. 이러한 키워드에 대해서는 참조를 해석하기 위해 기준 URI를 설정해야 합니다.¶
"$id" 키워드는 스키마 리소스를 그 정식 [RFC6596] URI로 식별합니다.¶
이 URI는 식별자이며 반드시 네트워크 위치자는 아님에 유의하십시오. 네트워크로 주소 지정 가능한 URL의 경우에도, 스키마가 정식 URI에서 다운로드 가능할 필요는 없습니다.¶
존재하는 경우, 이 키워드의 값은 문자열이어야 하며, 유효한 URI-reference [RFC3986]를 나타내야 합니다. 이 URI-reference는 정규화되는 것이 좋으며, 반드시 absolute-URI [RFC3986](프래그먼트 없음)로, 또는 빈 프래그먼트가 있는 URI로 해석되어야 합니다.¶
빈 프래그먼트 형식은 권장되지 않으며, 이전 버전과의 호환성 때문에, 그리고 application/schema+json 미디어 유형이 빈 프래그먼트가 있는 URI가 프래그먼트를 제거한 동일 URI와 같은 리소스를 식별한다고 정의하기 때문에만 유지됩니다. 그러나 이 동등성은 RFC 3986 정규화 과정 [RFC3986]의 일부가 아니므로, 구현자와 스키마 작성자는 일반 URI 라이브러리가 이를 이해한다고 의존할 수 없습니다.¶
따라서 "$id"는 비어 있지 않은 프래그먼트를 포함해서는 안 되며, 빈 프래그먼트도 포함하지 않는 것이 좋습니다. absolute-URI 형식은 빈 프래그먼트의 존재 여부와 관계없이 정식 URI로 간주되어야 합니다. 빈 프래그먼트는 오래된 메타 스키마가 자신의 $id(또는 이전의 id)에 빈 프래그먼트를 가지고 있기 때문에 현재 허용됩니다. 향후 초안에서는 "$id" 안의 빈 프래그먼트조차 전면 금지할 수 있습니다. ¶
또한 absolute-URI는 콘텐츠 안에 내장된 기준 URI에 관한 RFC 3986 5.1.1절 [RFC3986]에 따라, 스키마 리소스 안의 키워드에 있는 상대 URI-reference의 기준 URI로도 사용됩니다.¶
하위 스키마 안의 "$id" 존재는 그 하위 스키마가 단일 스키마 문서 안에서 별개의 스키마 리소스를 구성함을 나타냅니다. 또한 캡슐화된 엔터티에 관한 RFC 3986 5.1.2절 [RFC3986]에 따라, 하위 스키마 안의 "$id"가 상대 URI-reference라면, 그 참조를 해석하기 위한 기준 URI는 상위 스키마 리소스의 URI입니다.¶
어떤 상위 스키마 객체도 "$id"로 자신을 리소스로 명시적으로 식별하지 않는 경우, 기준 URI는 이전 섹션 (9.1.1절)에 제시된 단계에 따라 설정된 전체 문서의 URI입니다.¶
JSON 스키마 문서의 루트 스키마는 absolute-URI [RFC3986](스킴을 포함하지만 프래그먼트는 없음)를 가진 "$id" 키워드를 포함하는 것이 좋습니다.¶
JSON 포인터 프래그먼트를 사용하려면 스키마의 구조를 알아야 합니다. 재사용 가능한 스키마를 제공할 의도로 스키마 문서를 작성할 때는, 특정 구조적 위치에 묶이지 않은 일반 이름 프래그먼트를 사용하는 편이 더 바람직할 수 있습니다. 이렇게 하면 JSON 포인터 참조를 갱신할 필요 없이 하위 스키마를 재배치할 수 있습니다.¶
"$anchor" 및 "$dynamicAnchor" 키워드는 이러한 프래그먼트를 지정하는 데 사용됩니다. 이들은 "$id"에서 보이는 것처럼 절대 URI가 아니라 일반 이름 프래그먼트를 생성하는 데만 사용할 수 있는 식별자 키워드입니다.¶
그 결과 프래그먼트가 추가되는 기준 URI는 문제의 "$anchor" 또는 "$dynamicAnchor"를 포함하는 스키마 리소스의 정식 URI입니다. 이전 섹션에서 논의했듯이, 이는 같은 또는 상위 스키마 객체 안의 가장 가까운 "$id"이거나, RFC 3986에 따라 결정된 문서의 기준 URI입니다.¶
URI의 일반적인 사용과는 별도로, "$dynamicAnchor"는 "$dynamicRef" 키워드와 함께 사용될 때 그 프래그먼트가 확장 지점임을 나타냅니다. 이 저수준의 고급 기능은 메타 스키마 같은 재귀 스키마를 확장하기 쉽게 만들며, 그 확장에 특정한 의미를 부과하지 않습니다. 자세한 내용은 "$dynamicRef" (8.2.3.2절) 섹션을 참조하십시오.¶
대부분의 경우, 일반 프래그먼트 동작만으로도 충분하고 더 직관적입니다. 따라서 "$dynamicAnchor"가 명확히 필요한 경우가 아니라면 일반 이름 프래그먼트를 생성하는 데 "$anchor"를 사용하는 것이 권장됩니다.¶
존재하는 경우, 이 키워드의 값은 문자열이어야 하며, 문자([A-Za-z]) 또는 밑줄("_")로 시작하고, 그 뒤에 임의 개수의 문자, 숫자([0-9]), 하이픈("-"), 밑줄("_"), 마침표(".")가 이어져야 합니다. 이는 XML의 NCName 생성식 [xml-names]의 US-ASCII 부분과 일치합니다. 앵커 문자열은 URI-reference가 아니므로 "#" 문자를 포함하지 않는다는 점에 유의하십시오. "$anchor": "foo"는 URI에서 사용될 때 프래그먼트 "#foo"가 됩니다. 전체 예제는 아래를 참조하십시오. ¶
같은 리소스 안에서 "$anchor" 및/또는 "$dynamicAnchor"의 어떤 조합을 사용하든 동일한 프래그먼트 이름을 여러 번 지정하는 효과는 정의되지 않았습니다. 구현은 그러한 사용을 감지하면 오류를 일으킬 수 있습니다.¶
현재 인스턴스 위치에 적용될 스키마를 참조하기 위해 여러 키워드를 사용할 수 있습니다. "$ref"와 "$dynamicRef"는 참조된 스키마를 인스턴스에 적용하는 적용자 키워드입니다.¶
"$ref"와 "$dynamicRef"의 값은 URI References이므로, 스키마를 여러 파일로 외부화하거나 나눌 수 있는 가능성을 제공하며, 자기 참조를 통해 재귀 구조를 검증할 수 있는 기능을 제공합니다.¶
이러한 키워드가 생성하는 해석된 URI는 반드시 네트워크 위치자가 아니라 식별자일 뿐입니다. 스키마는 네트워크로 주소 지정 가능한 URL인 경우에도 해당 주소에서 다운로드 가능할 필요가 없으며, 구현은 네트워크로 주소 지정 가능한 URI를 만났다고 해서 네트워크 작업을 수행해야 한다고 가정해서는 안 됩니다.¶
"$ref" 키워드는 정적으로 식별된 스키마를 참조하는 데 사용되는 적용자입니다. 그 결과는 참조된 스키마의 결과입니다. 결과가 어떻게 결정되는지에 대한 이 정의는 같은 스키마 객체 안에서 "$ref"와 함께 다른 키워드가 나타날 수 있음을 의미합니다. ¶
"$ref" 키워드의 값은 URI-Reference인 문자열이어야 합니다. 현재 URI 기준에 대해 해석되면, 적용할 스키마의 URI를 생성합니다. 이 해석은 스키마 로드 시 안전하게 수행할 수 있습니다. 인스턴스를 평가하는 과정이 참조 해석 방식을 변경할 수 없기 때문입니다.¶
"$dynamicRef" 키워드는 전체 해석을 런타임까지 지연할 수 있게 하는 적용자이며, 그 시점에서 인스턴스를 평가하는 동안 만날 때마다 해석됩니다.¶
"$dynamicAnchor"와 함께 "$dynamicRef"는 주로 재귀 스키마 (자기 자신을 참조하는 스키마)에 유용한 협력적 확장 메커니즘을 구현합니다. 확장 지점과 런타임에 결정되는 확장 대상은 모두 "$dynamicAnchor"로 정의되며, "$dynamicRef"로 참조될 때만 런타임 동적 동작을 보입니다.¶
"$dynamicRef" 속성의 값은 URI-Reference인 문자열이어야 합니다. 현재 URI 기준에 대해 해석되면, 런타임 해석의 시작점으로 사용되는 URI를 생성합니다. 이 초기 해석은 스키마 로드 시 안전하게 수행할 수 있습니다.¶
초기 해석된 시작점 URI에 "$dynamicAnchor" 키워드가 생성한 프래그먼트가 포함되어 있다면, 초기 URI는 동일한 이름의 프래그먼트를 "$dynamicAnchor"로 정의하는 동적 범위 (7.1절) 안의 가장 바깥쪽 스키마 리소스에 대한 URI(프래그먼트 포함)로 대체되어야 합니다.¶
그렇지 않으면, 그 동작은 "$ref"와 동일하며 런타임 해석이 필요하지 않습니다.¶
이 키워드를 사용하는 전체 예제는 부록 C를 참조하십시오. 2019년 이전 초안의 hyper-schema 메타 스키마와 이 초안의 차이는 이러한 키워드의 유용성을 극적으로 보여줍니다. ¶
"$defs" 키워드는 스키마 작성자가 재사용 가능한 JSON 스키마를 더 일반적인 스키마 안에 인라인으로 넣기 위한 위치를 예약합니다. 이 키워드는 검증 결과에 직접 영향을 주지 않습니다.¶
이 키워드의 값은 객체여야 합니다. 이 객체의 각 멤버 값은 유효한 JSON 스키마여야 합니다.¶
예로, 다음은 양의 정수 제약이 "$defs" 안의 하위 스키마인 양의 정수 배열을 설명하는 스키마입니다:¶
{
"type": "array",
"items": { "$ref": "#/$defs/positiveInteger" },
"$defs": {
"positiveInteger": {
"type": "integer",
"exclusiveMinimum": 0
}
}
}
¶
이 키워드는 스키마 작성자가 스키마의 독자나 유지보수자에게 남기는 주석을 위한 위치를 예약합니다.¶
이 키워드의 값은 문자열이어야 합니다. 구현은 이 문자열을 최종 사용자에게 제시해서는 안 됩니다. 스키마 편집 도구는 이 키워드의 표시와 편집을 지원해야 합니다. 이 키워드의 값은 스키마를 사용하는 개발자를 대상으로 하는 디버그 또는 오류 출력에 사용될 수 있습니다.¶
스키마 어휘는 어휘 키워드를 포함하는 모든 객체 안에서 "$comment"를 허용해야 합니다. 어휘가 이를 구체적으로 금지하지 않는 한, 구현은 "$comment"가 허용된다고 가정할 수 있습니다. 어휘는 이 명세에 설명된 것 이상의 "$comment" 효과를 지정해서는 안 됩니다.¶
다른 미디어 유형이나 프로그래밍 언어를 application/schema+json으로 변환하거나 그 반대로 변환하는 도구는, 해당 미디어 유형이나 프로그래밍 언어의 네이티브 주석을 "$comment" 값으로 또는 그 반대로 변환하도록 선택할 수 있습니다. 네이티브 주석과 "$comment" 속성이 모두 존재할 때 이러한 변환의 동작은 구현에 따라 달라집니다.¶
구현은 처리 중 어느 시점에서든 "$comment" 값을 제거할 수 있습니다. 특히, 배포된 스키마의 크기가 문제가 될 때 스키마를 줄일 수 있게 합니다.¶
구현은 "$comment" 속성의 존재, 부재 또는 내용에 기반하여 다른 어떤 조치도 취해서는 안 됩니다. 특히 "$comment"의 값은 애너테이션 결과로 수집되어서는 안 됩니다.¶
RFC3986 5.1절 [RFC3986]은 문서의 기본 기준 URI를 결정하는 방법을 정의합니다.¶
정보적으로, 스키마의 초기 기준 URI는 그것이 발견된 URI입니다. 그것이 네트워크 위치이든, 로컬 파일 시스템이든, 알려진 어떤 스킴의 URI로 식별 가능한 다른 상황이든 마찬가지입니다.¶
스키마 문서가 "$id"(콘텐츠 안에 내장됨)로 명시적 기준 URI를 정의하지 않는 경우, 기준 URI는 RFC 3986 5절 [RFC3986]에 따라 결정됩니다.¶
출처를 알 수 없거나 출처의 URI 스킴을 알 수 없는 경우, RFC 3986 5.1.4절 [RFC3986]에 설명된 대로 적절한 구현별 기본 URI를 사용할 수 있습니다. 구현은 자신이 가정하는 기본 기준 URI를 문서화하는 것이 권장됩니다.¶
스키마 객체가 다른 미디어 유형의 문서 안에 내장되어 있다면, 초기 기준 URI는 그 미디어 유형의 규칙에 따라 결정됩니다.¶
앞선 섹션에서 설명한 "$id" 키워드가 루트 스키마에 존재하지 않는 한, 이 기준 URI는 스키마 문서 루트 스키마 리소스의 정식 URI로 간주되어야 합니다.¶
원격 스키마를 식별하기 위해 URI를 사용한다고 해서 반드시 무엇인가가 다운로드된다는 뜻은 아닙니다. 대신 JSON 스키마 구현은 자신이 어떤 스키마를 사용할지와, 그 스키마를 식별하는 URI를 미리 이해하고 있어야 합니다.¶
런타임이 되기 전까지 어떤 스키마를 다운로드할지 모르는 일반 사용자 에이전트처럼, 스키마가 다운로드되는 경우에는 하이퍼미디어에서의 사용 (9.5.1절)을 참조하십시오.¶
구현은 검증기가 스키마에 대해 가지는 신뢰에 따라 임의의 URI를 임의의 스키마와 연결하거나, 스키마의 "$id"가 제공한 URI를 자동으로 연결할 수 있어야 합니다. 이러한 URI와 스키마는 인스턴스를 처리하기 전에 구현에 제공될 수 있거나, 스키마 문서가 처리될 때 그 안에 기록되어 부록 A에 보인 것처럼 연결을 생성할 수 있습니다.¶
스키마는 여러 URI를 가질 수 있지만(그리고 그럴 가능성이 높지만), 하나의 URI가 둘 이상의 스키마를 식별할 방법은 없습니다. 여러 스키마가 같은 URI로 자신을 식별하려고 할 때, 검증기는 오류 조건을 일으키는 것이 좋습니다.¶
구현은 스키마가 다른 스키마의 "$schema" 키워드에 의해 메타 스키마로 식별되었기 때문에 검사되고 있다면, 그 스키마를 메타 스키마로 인식해야 합니다. 이는 단일 스키마 문서가 어떤 때는 일반 스키마로 간주되고, 다른 때는 메타 스키마로 간주될 수 있음을 의미합니다.¶
자기 자신의 메타 스키마인 스키마를 검사하는 경우, 구현이 이를 일반 스키마로 처리하기 시작하면 그 규칙에 따라 처리됩니다. 그러나 자기 자신의 "$schema" 값을 검사한 결과 두 번째로 로드될 때는 메타 스키마로 처리됩니다. 따라서 같은 문서는 한 세션의 과정에서 두 방식 모두로 처리됩니다.¶
구현은 자주 사용되는 메타 스키마를 미리 로드하고 그 어휘 지원 요구 사항을 미리 검사하는 것 같은 구현별 목적을 위해, 스키마가 명시적으로 메타 스키마로 전달되는 것을 허용할 수 있습니다. 메타 스키마 작성자는 이러한 기능이 구현 간에 상호운용될 것이라고 기대해서는 안 됩니다.¶
스키마는 JSON 포인터나 "$id"가 직접 부여한 URI를 포함하여 자신에게 부여된 어떤 URI로도 식별될 수 있습니다. 모든 경우에 "$ref" 참조를 역참조하는 것은 먼저 그 값을 현재 기준 URI에 대해 RFC 3986 [RFC3986]에 따라 URI 참조로 해석하는 것을 포함합니다.¶
그 결과 URI가 현재 문서 안의 스키마를 식별하거나, 구현에 제공된 다른 스키마 문서 안의 스키마를 식별한다면, 그 스키마는 자동으로 사용되어야 합니다.¶
예를 들어, 다음 스키마를 생각해 보십시오:¶
{
"$id": "https://example.net/root.json",
"items": {
"type": "array",
"items": { "$ref": "#item" }
},
"$defs": {
"single": {
"$anchor": "item",
"type": "object",
"additionalProperties": { "$ref": "other.json" }
}
}
}
¶
구현이 <#/$defs/single> 스키마를 만나면, "$anchor" 값을 현재 기준 URI에 대한 프래그먼트 이름으로 해석하여 <https://example.net/root.json#item>을 형성합니다.¶
그 다음 구현이 <#/items> 스키마 안을 들여다보면, <#item> 참조를 만나고, 이를 <https://example.net/root.json#item>으로 해석합니다. 이는 이 같은 문서 안에서 정의된 것으로 이미 보았으므로 자동으로 사용할 수 있습니다.¶
구현이 "other.json"에 대한 참조를 만나면, 이를 <https://example.net/other.json>으로 해석하는데, 이는 이 문서 안에 정의되어 있지 않습니다. 해당 식별자를 가진 스키마가 다른 방식으로 구현에 제공되었다면, 그것도 자동으로 사용할 수 있습니다. 참조된 스키마를 알 수 없을 때 구현은 무엇을 해야 하는가? 자동 네트워크 역참조가 허용되는 상황이 있는가? 동일 출처 정책인가? 사용자가 구성할 수 있는 옵션인가? Hyper-Schema가 설명하는 진화하는 API의 경우, 새 스키마가 시스템에 동적으로 추가될 것으로 예상되므로, 스키마 문서를 미리 로드해야 한다는 절대 요구 사항을 두는 것은 실행 가능하지 않습니다. ¶
JSON 포인터 URI 프래그먼트는 스키마 문서의 구조에 기반하여 구성되므로, 내장된 스키마 리소스와 그 하위 스키마는 자체 정식 URI에 상대적인 JSON 포인터 프래그먼트나, 포함하는 리소스의 URI에 상대적인 JSON 포인터 프래그먼트로 식별될 수 있습니다.¶
개념적으로, 연결된 스키마 리소스 집합은 각 리소스가 스키마 참조 (8.2.3절)로 연결된 별도 문서인지, 또는 하나 이상의 스키마 리소스가 하위 스키마로 내장된 단일 문서로 구성되었는지와 관계없이 동일하게 동작해야 합니다.¶
상위 스키마 리소스의 URI에 상대적인 JSON 포인터 프래그먼트를 포함하는 URI는 내장된 스키마가 별도 문서로 이동되어 참조될 때 유효하지 않게 되므로, 애플리케이션과 스키마는 그러한 URI를 사용하여 내장된 스키마 리소스나 그 안의 위치를 식별하지 않는 것이 좋습니다.¶
다른 스키마 리소스를 내장하고 있는 다음 스키마 문서를 생각해 보십시오:¶
{
"$id": "https://example.com/foo",
"items": {
"$id": "https://example.com/bar",
"additionalProperties": { }
}
}
¶
URI "https://example.com/foo#/items"는 내장된 리소스인 "items" 스키마를 가리킵니다. 그러나 그 스키마 리소스의 정식 URI는 "https://example.com/bar"입니다.¶
그 내장된 리소스 안의 "additionalProperties" 스키마에 대해, URI "https://example.com/foo#/items/additionalProperties"는 올바른 객체를 가리키지만, 그 객체가 자신 리소스의 정식 URI에 상대적으로 갖는 URI는 "https://example.com/bar#/additionalProperties"입니다.¶
이제 "$ref"에 URI 값을 사용하여 참조로 연결된 다음 두 스키마 리소스를 생각해 보십시오:¶
{
"$id": "https://example.com/foo",
"items": {
"$ref": "bar"
}
}
{
"$id": "https://example.com/bar",
"additionalProperties": { }
}
¶
여기서 "bar" 스키마 리소스의 정식 URI에 JSON 포인터 프래그먼트를 붙여 사용한 "https://example.com/bar#/additionalProperties"는 여전히 유효한 반면, "foo" 스키마 리소스의 정식 URI에 JSON 포인터 프래그먼트를 붙이는 데 의존했던 "https://example.com/foo#/items/additionalProperties"는 더 이상 아무것으로도 해석되지 않음을 볼 수 있습니다.¶
또한 "https://example.com/foo#/items"는 두 배열 모두에서 유효하지만 서로 다른 값으로 해석됨에 유의하십시오. 이 URI는 결국 리소스에 대한 검색 URI와 유사하게 기능합니다. 이 URI는 유효하지만, 두 번째(내장되지 않은) 배열에서 "$ref"를 포함하는 객체를 식별하고자 특별히 원하는 경우가 아니라면, 내장되거나 참조된 리소스의 "$id"를 사용하는 편이 더 견고합니다.¶
구현은 리소스의 정식 URI가 아닌 다른 기준과 그 기준에 상대적인 JSON 포인터 프래그먼트를 사용한 URI로 스키마 리소스 내용을 주소 지정하는 것을 지원하지 않도록 선택할 수 있습니다. 따라서 스키마 작성자는 그러한 URI에 의존하지 않는 것이 좋습니다. 이를 사용하면 상호운용성이 줄어들 수 있기 때문입니다. 이는 각 스키마 리소스에 대해 가능한 기준 URI와 JSON 포인터 프래그먼트의 전체 스택을 구현이 추적하도록 요구하는 것을 피하기 위한 것입니다. 그중 하나를 제외한 모두는 스키마 리소스가 재구성되면 취약해지기 때문입니다. 어떤 사람들은 이것이 쉬우므로 금지할 이유가 없다고 주장한 반면, 다른 사람들은 이것이 스키마 식별을 복잡하게 하므로 금지되어야 한다고 주장했습니다. 이 주제에 대한 피드백을 권장합니다. 일부 논의 후, 우리는 "canonical"의 사용을 제거하고 스키마 리소스 경계를 가로질러 참조하는 JSON 포인터를 정의되지 않았거나 심지어 금지된 동작으로 말할 필요가 있다고 느낍니다. (https://github.com/json-schema-org/json-schema-spec/issues/937, https://github.com/json-schema-org/json-schema-spec/issues/1183) ¶
이러한 비정식 URI 구성의 추가 예와 대신 사용할 적절한 정식 URI 기반 프래그먼트는 부록 A에 제공되어 있습니다.¶
복합 스키마 문서는 전송을 쉽게 하기 위해 여러 내장 JSON 스키마 리소스를 같은 문서 안에 묶은 JSON 문서(때로는 "번들된" 스키마라고 함)로 정의됩니다.¶
각 내장 스키마 리소스는 어휘 지원 결정 등 표준 스키마 로드 및 처리 요구 사항을 따르는 개별 스키마 리소스로 처리되어야 합니다.¶
복합 스키마 문서를 만들기 위한 번들링 과정은 외부 스키마 리소스에 대한 참조(예: "$ref")를 가져와, 참조된 스키마 리소스를 참조하는 문서 안에 내장하는 것으로 정의됩니다. 번들링은 기준 문서와 모든 참조/내장 문서 안의 모든 URI(참조에 사용되는 것)를 변경할 필요가 없도록 수행하는 것이 좋습니다.¶
각 내장 JSON 스키마 리소스는 "$id" 키워드를 사용하여 URI로 자신을 식별해야 하며, 스키마 리소스의 루트에서 자신이 사용하는 방언을 식별하기 위해 "$schema" 키워드를 사용하는 것이 좋습니다. "$id"의 URI 식별자 값은 Absolute URI인 것이 권장됩니다.¶
참조 기반 적용자가 참조하는 스키마 리소스가 번들될 때, 그 스키마 리소스는 포함하는 스키마의 루트에 있는 "$defs" 객체의 값으로 위치하는 것이 권장됩니다. 이제 내장된 스키마 리소스에 대한 "$defs"의 키는 번들된 스키마의 "$id"이거나, UUID 같은 애플리케이션 정의 고유 식별자의 다른 형태일 수 있습니다. 이 키는 JSON 스키마에서 참조되도록 의도된 것이 아니지만, 애플리케이션이 번들링 과정을 돕기 위해 사용할 수 있습니다.¶
스키마 리소스는 그 위치가 스키마 값으로 정의된 경우 "$defs"가 아닌 위치에 내장될 수 있습니다.¶
번들된 스키마 리소스는 그것이 참조되었던 스키마 객체를 대체하거나, 스키마 리소스를 다른 적용자 키워드로 감싸는 방식으로 번들되어서는 안 됩니다.¶
동일한 출력을 생성하기 위해, 포함하는 스키마 문서 안에서 이전에 외부였던 스키마 리소스를 가리키는 참조는 변경되어서는 안 되며, 이제 내장된 스키마 리소스의 "$id"를 사용하여 스키마로 해석되어야 합니다. 이러한 동일한 출력에는 검증 평가와 결과 애너테이션 또는 오류에 사용되는 URI나 경로가 포함됩니다.¶
번들링 과정은 복합 스키마 문서를 만드는 주된 방법인 경우가 많지만, 일부는 개별 스키마 리소스가 이전에 독립적으로 존재하지 않은 상태에서 손으로 만들어질 수도 있고 그렇게 될 것으로 예상됩니다.¶
여러 스키마 리소스가 단일 문서 안에 존재할 때, 어떤 방언으로 처리되어야 하는지 정의하지 않는 스키마 리소스는 둘러싸는 리소스와 같은 방언으로 처리되어야 합니다.¶
참조될 수 있는 모든 스키마는 내장될 수도 있으므로, 내장된 스키마 리소스는 둘러싸는 리소스의 "$schema" 값과 다른 처리 방언을 지정할 수 있습니다.¶
복합 스키마 문서는 서로 다른 방언을 사용하는 것으로 식별되는 내장 리소스를 가질 수 있으므로, 이러한 문서는 복합 스키마 문서를 인스턴스로 삼아 메타 스키마를 적용하는 방식으로 검증하지 않는 것이 좋습니다. 스키마 문서를 검증하기 위한 대체 검증 과정을 제공하는 것이 권장됩니다. 각 스키마 리소스는 그에 연결된 메타 스키마에 대해 별도로 검증되어야 합니다. 검증되는 것이 스키마라는 사실을 알고 있다면, "$id" 사용을 통해 그 스키마가 복합 스키마 문서인지 아닌지 식별할 수 있습니다. "$id"는 문서의 루트가 아닌 곳에서 사용될 때 내장된 리소스를 식별합니다. ¶
모든 내장 리소스가 같은 방언을 사용하는 것으로 식별되거나, "$schema"가 생략되어 둘러싸는 리소스의 방언으로 기본 설정되는 복합 스키마 문서는 적절한 메타 스키마를 적용하여 검증될 수 있습니다.¶
스키마는 인스턴스에 대해 무한 루프에 빠져서는 안 됩니다. 예를 들어, 두 스키마 "#alice"와 "#bob"이 모두 서로를 참조하는 "allOf" 속성을 가진다면, 단순한 검증기는 인스턴스를 검증하려고 무한 재귀 루프에 빠질 수 있습니다. 스키마는 이러한 무한 재귀 중첩을 사용하지 않는 것이 좋으며, 그 동작은 정의되지 않았습니다.¶
하위 스키마 객체(또는 불리언)는 알려진 적용자 키워드와 함께 사용되거나 하나 이상의 하위 스키마를 값으로 받는 "$defs" (8.2.4절) 같은 위치 예약 키워드와 함께 사용됨으로써 인식됩니다. 이러한 키워드는 "$defs"와 이 문서의 표준 적용자, 알려진 어휘의 확장 키워드, 또는 구현별 사용자 정의 키워드일 수 있습니다.¶
알 수 없는 키워드의 다중 수준 구조는 중첩된 하위 스키마를 도입할 수 있으며, 이는 "$id"에 대한 처리 규칙의 대상이 됩니다. 따라서 그러한 인식되지 않은 구조 안에 참조 대상이 있는 것은 신뢰성 있게 구현할 수 없으며, 결과 동작은 정의되지 않았습니다. 마찬가지로, 값이 스키마가 아님이 알려진 알려진 키워드 아래의 참조 대상도 정의되지 않은 동작을 초래합니다. 이는 구현이 그러한 대상을 감지해야 하는 부담을 피하기 위한 것입니다. 이러한 시나리오는 HTTP로 스키마를 가져오지만 application/schema+json이 아닌 Content-Type을 가진 응답을 받는 것과 유사합니다. 구현은 물론 이를 스키마로 해석하려고 시도할 수 있지만, 원본 서버는 그것이 실제로 그런 것이라는 보장을 제공하지 않았습니다. 따라서 그렇게 해석하는 것은 보안상의 함의를 가지며 예측 불가능한 결과를 만들 수 있습니다. ¶
"$defs"와 동일한 구문 및 의미를 가진 단일 수준 사용자 정의 키워드는 그 사이에 "$id" 키워드가 끼어들 수 없으므로, 어떤 참조 대상이든 스키마로 사용하려고 시도하는 구현 아래에서 올바르게 동작한다는 점에 유의하십시오. 그러나 이 동작은 구현별이며 상호운용성을 위해 의존해서는 안 됩니다.¶
JSON은 자동화된 API와 로봇을 위해 HTTP 서버에서 널리 채택되었습니다. 이 섹션은 미디어 유형과 웹 링크 [RFC8288]를 지원하는 프로토콜과 함께 사용할 때, JSON 문서 처리를 더 RESTful한 방식으로 향상하는 방법을 설명합니다.¶
스키마로 설명되는 인스턴스는 Linked Data Protocol 1.0, 8.1절 [W3C.REC-ldp-20150226]에 정의된 대로 링크 관계 "describedby"를 사용하여 다운로드 가능한 JSON 스키마에 대한 링크를 제공하는 것이 권장됩니다.¶
HTTP에서는 이러한 링크를 Link 헤더 [RFC8288]를 사용하여 어떤 응답에도 첨부할 수 있습니다. 그러한 헤더의 예는 다음과 같습니다:¶
Link: <https://example.com/my-hyper-schema>; rel="describedby"
¶
네트워크를 통한 하이퍼미디어 시스템에 사용될 때, HTTP [RFC7231]는 스키마를 배포하기 위해 자주 선택되는 프로토콜입니다. 잘못 동작하는 클라이언트는 스키마를 오랫동안 캐시할 수 있는데도 필요 이상으로 자주 네트워크를 통해 가져오면 서버 유지보수자에게 문제를 일으킬 수 있습니다.¶
HTTP 서버는 JSON 스키마에 장기간 유효한 캐싱 헤더를 설정해야 합니다. HTTP 클라이언트는 캐싱 헤더를 준수하고 신선도 기간 내에는 문서를 다시 요청하지 않아야 합니다. 분산 시스템은 공유 캐시 및/또는 캐싱 프록시를 사용해야 합니다.¶
클라이언트는 JSON 스키마 구현 또는 소프트웨어 제품에 특화된 User-Agent 헤더를 설정하거나 앞에 붙여야 합니다. 기호는 중요도가 감소하는 순서로 나열되므로, JSON 스키마 라이브러리 이름/버전은 더 일반적인 HTTP 라이브러리 이름(있는 경우)보다 앞에 와야 합니다. 예를 들면 다음과 같습니다:¶
User-Agent: product-name/5.4.1 so-cool-json-schema/1.0.2 curl/7.43.0
¶
클라이언트는 서버 운영자가 잘못 동작할 가능성이 있는 스크립트의 소유자에게 연락할 수 있도록 "From" 헤더로 요청할 수 있어야 합니다.¶
이 섹션은 다른 어휘의 기반으로 사용하도록 권장되는 적용자 키워드의 어휘를 정의합니다.¶
"$vocabulary"를 사용하지 않는 메타 스키마는 그 URI가 true 값과 함께 존재하는 것처럼 이 어휘를 요구하는 것으로 간주되어야 합니다.¶
Applicator 어휘로 알려진 이 어휘의 현재 URI는 다음과 같습니다: <https://json-schema.org/draft/2020-12/vocab/applicator>.¶
대응하는 메타 스키마의 현재 URI는 다음과 같습니다: https://json-schema.org/draft/2020-12/meta/applicator.¶
스키마 키워드는 일반적으로 서로의 결과에 영향을 주지 않고 독립적으로 작동합니다.¶
스키마 작성자의 편의를 위해, 이 어휘의 키워드 중에는 몇 가지 예외가 있습니다:¶
이 키워드들은 상위 스키마가 적용되는 인스턴스의 같은 위치에 하위 스키마를 적용합니다. 이들은 다양한 방식으로 하위 스키마 결과를 결합하거나 수정할 수 있게 합니다.¶
이러한 키워드의 하위 스키마는 완전히 독립적으로 인스턴스를 평가하므로, 한 하위 스키마의 결과가 형제 하위 스키마의 결과에 영향을 주어서는 안 됩니다. 따라서 하위 스키마는 어떤 순서로든 적용될 수 있습니다.¶
이 키워드들은 하위 스키마의 불리언 단언 결과를 결합하거나 수정하기 위한 논리 연산자에 해당합니다. 이들은 애너테이션 수집에 직접 영향을 주지는 않지만, 같은 애너테이션 키워드가 서로 다른 값으로 인스턴스 위치에 적용될 수 있게 합니다. 애너테이션 키워드는 그러한 값을 결합하기 위한 자체 규칙을 정의합니다.¶
이 키워드의 값은 비어 있지 않은 배열이어야 합니다. 배열의 각 항목은 유효한 JSON 스키마여야 합니다.¶
인스턴스는 이 키워드의 값으로 정의된 모든 스키마에 대해 성공적으로 검증되면 이 키워드에 대해 성공적으로 검증됩니다.¶
이 키워드의 값은 비어 있지 않은 배열이어야 합니다. 배열의 각 항목은 유효한 JSON 스키마여야 합니다.¶
인스턴스는 이 키워드의 값으로 정의된 스키마 중 하나 이상에 대해 성공적으로 검증되면 이 키워드에 대해 성공적으로 검증됩니다. 애너테이션을 수집하는 경우, 성공적으로 검증되는 각 하위 스키마에서 애너테이션이 수집되도록 모든 하위 스키마를 검사해야 합니다.¶
이 키워드의 값은 비어 있지 않은 배열이어야 합니다. 배열의 각 항목은 유효한 JSON 스키마여야 합니다.¶
인스턴스는 이 키워드의 값으로 정의된 스키마 중 정확히 하나에 대해 성공적으로 검증되면 이 키워드에 대해 성공적으로 검증됩니다.¶
이 키워드 중 세 개는 함께 작동하여 다른 하위 스키마의 결과에 기반한 하위 스키마의 조건부 적용을 구현합니다. 네 번째는 특정 조건 사례를 위한 단축 표현입니다.¶
"if", "then", "else"는 하위 스키마 경계를 넘어 서로 상호작용해서는 안 됩니다. 다시 말해, "allOf"의 한 분기 안의 "if"는 다른 분기 안의 "then" 또는 "else"에 영향을 주어서는 안 됩니다.¶
"if", "then", "else"가 존재하지 않을 때의 기본 동작은 없습니다. 특히 이들은 빈 스키마와 함께 존재하는 것처럼 처리되어서는 안 되며, "if"가 존재하지 않을 때 "then"과 "else"는 모두 완전히 무시되어야 합니다.¶
이 키워드의 값은 유효한 JSON 스키마여야 합니다.¶
이 키워드의 하위 스키마에 대한 검증 결과는 전체 검증 결과에 직접 영향을 주지 않습니다. 대신 "then" 또는 "else" 키워드 중 어느 것이 평가되는지를 제어합니다.¶
이 키워드의 하위 스키마에 대해 성공적으로 검증되는 인스턴스는, "then" 키워드가 존재한다면 그 하위 스키마 값에 대해서도 유효해야 합니다.¶
이 키워드의 하위 스키마에 대해 검증에 실패하는 인스턴스는, "else" 키워드가 존재한다면 그 하위 스키마 값에 대해서도 유효해야 합니다.¶
애너테이션 (7.7절)을 수집하는 경우, "then" 또는 "else" 없이 이 키워드가 존재하는 경우를 포함하여, 애너테이션은 일반적인 방식으로 이 키워드의 하위 스키마에서 수집됩니다.¶
이 키워드의 값은 유효한 JSON 스키마여야 합니다.¶
"if"가 존재하고 인스턴스가 그 하위 스키마에 대해 성공적으로 검증될 때, 이 키워드의 하위 스키마에 대해서도 인스턴스가 성공적으로 검증되면 이 키워드에 대한 검증이 성공합니다.¶
이 키워드는 "if"가 없거나, 인스턴스가 그 하위 스키마에 대해 검증에 실패할 때 아무 효과가 없습니다. 구현은 그러한 경우 검증 목적이든 애너테이션 수집 목적이든 이 키워드에 대해 인스턴스를 평가해서는 안 됩니다.¶
이 키워드의 값은 유효한 JSON 스키마여야 합니다.¶
"if"가 존재하고 인스턴스가 그 하위 스키마에 대해 검증에 실패할 때, 인스턴스가 이 키워드의 하위 스키마에 대해 성공적으로 검증되면 이 키워드에 대한 검증이 성공합니다.¶
이 키워드는 "if"가 없거나, 인스턴스가 그 하위 스키마에 대해 성공적으로 검증될 때 아무 효과가 없습니다. 구현은 그러한 경우 검증 목적이든 애너테이션 수집 목적이든 이 키워드에 대해 인스턴스를 평가해서는 안 됩니다.¶
이 키워드는 인스턴스가 객체이고 특정 속성을 포함할 때 평가되는 하위 스키마를 지정합니다.¶
이 키워드의 값은 객체여야 합니다. 객체 안의 각 값은 유효한 JSON 스키마여야 합니다.¶
객체 키가 인스턴스 안의 속성이라면, 전체 인스턴스는 그 하위 스키마에 대해 검증되어야 합니다. 그 사용은 속성의 존재에 의존합니다.¶
이 키워드를 생략하는 것은 빈 객체와 같은 동작을 가집니다.¶
이들 각 키워드는 하위 스키마를 자식 인스턴스, 특히 객체 속성과 배열 항목에 적용하고, 그 결과를 결합하기 위한 규칙을 정의합니다.¶
"prefixItems"의 값은 유효한 JSON 스키마의 비어 있지 않은 배열이어야 합니다.¶
인스턴스의 각 요소가 같은 위치에 있는 스키마에 대해, 있는 경우, 검증되면 검증이 성공합니다. 이 키워드는 배열의 길이를 제한하지 않습니다. 배열이 이 키워드의 값보다 길면, 이 키워드는 일치하는 길이의 접두부만 검증합니다.¶
이 키워드는 이 키워드가 하위 스키마를 적용한 가장 큰 인덱스를 애너테이션 값으로 생성합니다. "items" 키워드가 생성하는 것처럼, 하위 스키마가 인스턴스의 모든 인덱스에 적용되었다면 값은 불리언 true일 수 있습니다. 이 애너테이션은 "items" 및 "unevaluatedItems"의 동작에 영향을 줍니다.¶
이 키워드를 생략하는 것은 빈 배열과 같은 단언 동작을 가집니다.¶
"items"의 값은 유효한 JSON 스키마여야 합니다.¶
이 키워드는 같은 스키마 객체 안의 "prefixItems" 키워드의 애너테이션 결과가 보고한 "prefixItems" 배열의 길이보다 큰 인덱스에 있는 모든 인스턴스 요소에 자신의 하위 스키마를 적용합니다. 그러한 애너테이션 결과가 없으면, "items"는 자신의 하위 스키마를 모든 인스턴스 배열 요소에 적용합니다. "prefixItems" 없는 "items"의 동작은 이전 초안의 "items" 스키마 형식의 동작과 동일하다는 점에 유의하십시오. "prefixItems"가 존재할 때, "items"의 동작은 이전 "additionalItems" 키워드와 동일합니다. ¶
"items" 하위 스키마가 인스턴스 배열 안의 어떤 위치에든 적용되면, 모든 남은 배열 요소가 이 키워드의 하위 스키마에 대해 평가되었음을 나타내는 불리언 true의 애너테이션 결과를 생성합니다. 이 애너테이션은 Unevaluated 어휘의 "unevaluatedItems" 동작에 영향을 줍니다.¶
이 키워드를 생략하는 것은 빈 스키마와 같은 단언 동작을 가집니다.¶
구현은 "prefixItems" 배열의 존재와 크기를 직접 확인하는 것과 같이 같은 효과를 생성하는 다른 방식으로 이 키워드를 구현하거나 최적화하도록 선택할 수 있습니다. 애너테이션 수집을 지원하지 않는 구현은 그렇게 해야 합니다.¶
이 키워드의 값은 유효한 JSON 스키마여야 합니다.¶
배열 인스턴스는 그 요소 중 하나 이상이 주어진 스키마에 대해 유효하면 "contains"에 대해 유효합니다. 단, "minContains"가 존재하고 값이 0인 경우에는 어떤 요소도 주어진 스키마에 대해 유효하지 않더라도 배열 인스턴스는 "contains" 키워드에 대해 유효한 것으로 간주되어야 합니다.¶
이 키워드는 하위 스키마를 적용할 때 이 키워드가 성공적으로 검증되는 인덱스들의 배열을 오름차순으로 애너테이션 값으로 생성합니다. 하위 스키마가 인스턴스의 모든 인덱스에 적용될 때 성공적으로 검증된다면, 값은 불리언 "true"일 수 있습니다. 이 키워드의 스키마가 적용되는 인스턴스 배열이 비어 있다면 애너테이션은 반드시 존재해야 합니다.¶
이 애너테이션은 Unevaluated 어휘의 "unevaluatedItems" 동작에 영향을 주며, 검증 어휘의 "minContains" 및 "maxContains" 키워드를 구현하는 데에도 사용될 수 있습니다.¶
다른 키워드가 사용할 애너테이션을 수집하기 위해, 첫 번째 일치 항목이 발견된 뒤에도 하위 스키마는 모든 배열 요소에 적용되어야 합니다. 이는 가능한 모든 애너테이션이 수집되도록 보장하기 위한 것입니다.¶
"properties"의 값은 객체여야 합니다. 이 객체의 각 값은 유효한 JSON 스키마여야 합니다.¶
인스턴스와 이 키워드의 값 안에 이름으로 모두 나타나는 각 이름에 대해, 해당 이름의 자식 인스턴스가 대응하는 스키마에 대해 성공적으로 검증되면 검증이 성공합니다.¶
이 키워드의 애너테이션 결과는 이 키워드가 일치시킨 인스턴스 속성 이름의 집합입니다. 이 애너테이션은 이 어휘의 "additionalProperties"와 Unevaluated 어휘의 "unevaluatedProperties" 동작에 영향을 줍니다.¶
이 키워드를 생략하는 것은 빈 객체와 같은 단언 동작을 가집니다.¶
"patternProperties"의 값은 객체여야 합니다. 이 객체의 각 속성 이름은 ECMA-262 정규 표현식 방언에 따른 유효한 정규 표현식이어야 합니다. 이 객체의 각 속성 값은 유효한 JSON 스키마여야 합니다.¶
이 키워드의 값 안에 속성 이름으로 나타나는 정규 표현식 중 하나와 일치하는 각 인스턴스 이름에 대해, 그 이름의 자식 인스턴스가 일치하는 정규 표현식에 대응하는 각 스키마에 대해 성공적으로 검증되면 검증이 성공합니다.¶
이 키워드의 애너테이션 결과는 이 키워드가 일치시킨 인스턴스 속성 이름의 집합입니다. 이 애너테이션은 이 어휘의 "additionalProperties"와 Unevaluated 어휘의 "unevaluatedProperties" 동작에 영향을 줍니다.¶
이 키워드를 생략하는 것은 빈 객체와 같은 단언 동작을 가집니다.¶
"additionalProperties"의 값은 유효한 JSON 스키마여야 합니다.¶
이 키워드의 동작은 같은 스키마 객체 안의 "properties"와 "patternProperties"의 존재 및 애너테이션 결과에 의존합니다. "additionalProperties"를 사용한 검증은 "properties" 또는 "patternProperties" 어느 쪽의 애너테이션 결과에도 나타나지 않는 인스턴스 이름의 자식 값에만 적용됩니다.¶
그러한 모든 속성에 대해, 자식 인스턴스가 "additionalProperties" 스키마에 대해 검증되면 검증이 성공합니다.¶
이 키워드의 애너테이션 결과는 이 키워드의 하위 스키마가 검증한 인스턴스 속성 이름의 집합입니다. 이 애너테이션은 Unevaluated 어휘의 "unevaluatedProperties" 동작에 영향을 줍니다.¶
이 키워드를 생략하는 것은 빈 스키마와 같은 단언 동작을 가집니다.¶
구현은 "properties"의 이름과 "patternProperties"의 패턴을 인스턴스 속성 집합에 대해 직접 확인하는 것과 같이 같은 효과를 생성하는 다른 방식으로 이 키워드를 구현하거나 최적화하도록 선택할 수 있습니다. 애너테이션 수집을 지원하지 않는 구현은 그렇게 해야 합니다. 이 옵션을 정의하면서 출력 형식에 모호성이 생길 가능성이 있어 보입니다. 그 모호성은 검증 결과에는 영향을 주지 않지만, 결과 출력 형식에는 영향을 줍니다. 이 모호성은 애너테이션이 사용되는지, 또는 draft-07과 "같은 효과를 생성하는" 해결책이 사용되는지에 따라 여러 유효한 출력 결과를 허용합니다. 실패한 스키마의 애너테이션은 버려지는 것으로 이해됩니다. 자세한 내용은 우리의 [Decision Record](https://github.com/json-schema-org/json-schema-spec/tree/HEAD/adr/2022-04-08-cref-for-ambiguity-and-fix-later-gh-spec-issue-1172.md) 를 참조하십시오. ¶
"propertyNames"의 값은 유효한 JSON 스키마여야 합니다.¶
인스턴스가 객체인 경우, 인스턴스의 모든 속성 이름이 제공된 스키마에 대해 검증되면 이 키워드는 검증됩니다. 스키마가 테스트하는 속성 이름은 항상 문자열임에 유의하십시오.¶
이 키워드를 생략하는 것은 빈 스키마와 같은 동작을 가집니다.¶
이 키워드들의 목적은 스키마 작성자가 인접 키워드의 어떤 동적 범위 하위 스키마에 대해서도 성공적으로 평가되지 않은 배열 항목이나 객체 속성에 하위 스키마를 적용할 수 있게 하는 것입니다.¶
이러한 인스턴스 항목이나 속성은 "anyOf"의 한 분기에서 단언이 실패하는 경우처럼 하나 이상의 인접 키워드 하위 스키마에 대해 성공적으로 평가되지 않았을 수 있습니다. 이러한 실패한 평가는 해당 항목이나 속성이 평가되었는지 여부에 기여하는 것으로 간주되지 않습니다. 성공한 평가만 고려됩니다.¶
배열의 항목이나 객체 속성이 "성공적으로 평가"되었다면, 이는 예상되는 객체나 배열 표현의 관점에서 논리적으로 유효한 것으로 간주됩니다. 예를 들어 하위 스키마가 2~4개의 바퀴를 요구하는 자동차를 나타내고, "wheels"의 값이 6이라면, 인스턴스 객체는 자동차로 "평가"되지 않으며, "wheels" 속성은 "평가되지 않은 것(알려진 것으로서 성공적으로)"으로 간주되고, 어떤 애너테이션도 보존하지 않습니다.¶
인접 키워드는 같은 스키마 객체 안의 키워드이며, 동적 범위 하위 스키마에는 어휘적 하위 스키마뿐만 아니라 참조 대상도 포함된다는 점을 상기하십시오.¶
이러한 키워드들의 동작은 검증 중인 인스턴스 위치에 적용되는 인접 키워드의 애너테이션 결과에 의존합니다.¶
"$vocabulary"를 사용하지 않는 메타 스키마는 그 URI가 true 값과 함께 존재하는 것처럼 이 어휘를 요구하는 것으로 간주되어야 합니다.¶
Unevaluated Applicator 어휘로 알려진 이 어휘의 현재 URI는 다음과 같습니다: <https://json-schema.org/draft/2020-12/vocab/unevaluated>.¶
대응하는 메타 스키마의 현재 URI는 다음과 같습니다: https://json-schema.org/draft/2020-12/meta/unevaluated.¶
스키마 키워드는 일반적으로 서로의 결과에 영향을 주지 않고 독립적으로 동작합니다. 그러나 이 어휘의 키워드들은 주목할 만한 예외입니다:¶
"unevaluatedItems"의 값은 유효한 JSON 스키마여야 합니다.¶
이 키워드의 동작은 검증 중인 인스턴스 위치에 적용되는 인접 키워드의 애너테이션 결과에 의존합니다. 구체적으로, "unevaluatedItems" 키워드에 인접할 때 해당 키워드들에서 나올 수 있는 "prefixItems", "items" 및 "contains"의 애너테이션입니다. 이 세 애너테이션뿐만 아니라 "unevaluatedItems"도 모든 인접 제자리 적용자 (10.2절) 키워드에서 결과로 나올 수 있습니다. 여기에는 이 문서에서 정의한 제자리 적용자가 포함되지만 이에 한정되지는 않습니다.¶
관련 애너테이션이 없으면, "unevaluatedItems" 하위 스키마는 배열의 모든 위치에 적용되어야 합니다. 관련 애너테이션 중 하나에서 불리언 true 값이 존재하면, "unevaluatedItems"는 무시되어야 합니다. 그렇지 않으면, 하위 스키마는 "prefixItems"에 대한 가장 큰 애너테이션 값보다 큰 인덱스 중, "contains"에 대한 어떤 애너테이션 값에도 나타나지 않는 모든 인덱스에 적용되어야 합니다.¶
이는 이 키워드를 평가하기 전에 "prefixItems", "items", "contains" 및 모든 제자리 적용자가 평가되어야 함을 의미합니다. 확장 키워드 작성자는 이 키워드 이후에 평가되어야 할 필요가 있는 제자리 적용자를 정의해서는 안 됩니다.¶
"unevaluatedItems" 하위 스키마가 인스턴스 배열 안의 어떤 위치에든 적용되면, "items"의 동작과 유사하게 불리언 true의 애너테이션 결과를 생성합니다. 이 애너테이션은 상위 스키마의 "unevaluatedItems" 동작에 영향을 줍니다.¶
이 키워드를 생략하는 것은 빈 스키마와 같은 단언 동작을 가집니다.¶
"unevaluatedProperties"의 값은 유효한 JSON 스키마여야 합니다.¶
이 키워드의 동작은 검증 중인 인스턴스 위치에 적용되는 인접 키워드의 애너테이션 결과에 의존합니다. 구체적으로, "unevaluatedProperties" 키워드에 인접할 때 해당 키워드들에서 나올 수 있는 "properties", "patternProperties", "additionalProperties"의 애너테이션입니다. 이 세 애너테이션뿐만 아니라 "unevaluatedProperties"도 모든 인접 제자리 적용자 (10.2절) 키워드에서 결과로 나올 수 있습니다. 여기에는 이 문서에서 정의한 제자리 적용자가 포함되지만 이에 한정되지는 않습니다.¶
"unevaluatedProperties"를 사용한 검증은 검증 중인 인스턴스 위치에 적용되는 "properties", "patternProperties", "additionalProperties" 또는 "unevaluatedProperties" 애너테이션 결과에 나타나지 않는 인스턴스 이름의 자식 값에만 적용됩니다.¶
그러한 모든 속성에 대해, 자식 인스턴스가 "unevaluatedProperties" 스키마에 대해 검증되면 검증이 성공합니다.¶
이는 이 키워드를 평가하기 전에 "properties", "patternProperties", "additionalProperties" 및 모든 제자리 적용자가 평가되어야 함을 의미합니다. 확장 키워드 작성자는 이 키워드 이후에 평가되어야 할 필요가 있는 제자리 적용자를 정의해서는 안 됩니다.¶
이 키워드의 애너테이션 결과는 이 키워드의 하위 스키마가 검증한 인스턴스 속성 이름의 집합입니다. 이 애너테이션은 상위 스키마의 "unevaluatedProperties" 동작에 영향을 줍니다.¶
이 키워드를 생략하는 것은 빈 스키마와 같은 단언 동작을 가집니다.¶
JSON 스키마는 플랫폼 독립적으로 정의됩니다. 따라서 플랫폼 간 호환성을 높이기 위해, 구현은 표준 검증 출력 형식을 따르는 것이 좋습니다. 이 섹션은 소비자가 검증 결과를 올바르게 해석하는 데 필요한 최소 요구 사항을 설명합니다.¶
JSON 스키마 출력은 4.2.1절에 설명된 JSON 스키마 데이터 인스턴스 모델을 사용하여 정의됩니다. 구현은 특정 언어와 플랫폼에서 지원하는 바에 따라 이와 다를 수 있지만, 출력은 직렬화나 다른 수단을 통해 여기에서 정의한 JSON 형식으로 변환 가능하도록 하는 것이 권장됩니다.¶
이 명세는 네 가지 출력 형식을 정의합니다. 각 형식의 요구 사항은 "출력 구조" 섹션을 참조하십시오.¶
구현은 "flag", "basic" 또는 "detailed" 형식 중 적어도 하나를 제공해야 하며, "verbose" 형식을 제공할 수 있습니다. "detailed" 또는 "verbose" 형식 중 하나 이상을 제공한다면, "flag" 형식도 제공해야 합니다. 구현은 자신이 지원하는 형식을 문서에 명시하는 것이 좋습니다.¶
단순한 "flag" 출력 외에도, 스키마나 인스턴스를 디버깅하는 데 도움이 되는 추가 정보가 유용합니다. 각 하위 결과는 최소한 이 섹션에 포함된 정보를 담는 것이 좋습니다.¶
이러한 모든 구성 요소를 포함하는 단일 객체는 출력 단위로 간주됩니다.¶
구현은 추가 정보를 제공하도록 선택할 수 있습니다.¶
검증 경로를 따르는 검증 키워드의 상대 위치입니다. 값은 JSON 포인터로 표현되어야 하며, "$ref" 또는 "$dynamicRef" 같은 모든 참조 기반 적용자를 포함해야 합니다.¶
/properties/width/$ref/minimum¶
이러한 참조 기반 적용자 키워드가 포함되어 있기 때문에, 이 포인터는 일반 JSON 포인터 과정으로는 해석되지 않을 수 있음에 유의하십시오.¶
이 정보에 대한 JSON 키는 "keywordLocation"입니다.¶
검증 키워드의 절대적이고 역참조된 위치입니다. 값은 관련 스키마 리소스의 정식 URI와 JSON 포인터 프래그먼트를 사용한 전체 URI로 표현되어야 하며, "$ref" 또는 "$dynamicRef" 같은 참조 기반 적용자를 비말단 경로 구성 요소로 포함해서는 안 됩니다. 오류나 애너테이션이 해당 키워드에 대한 것이라면, 예컨대 해석할 수 없는 참조처럼, 그러한 키워드로 끝날 수는 있습니다. 여기서 "absolute"는 RFC 3986의 "absolute-URI" 용어(스킴은 있지만 프래그먼트는 없음을 의미)가 아니라 "절대 파일 시스템 경로"(완전한 위치를 의미)의 의미임에 유의하십시오. 키워드 절대 위치는 키워드를 식별하기 위해 프래그먼트를 가질 것입니다. ¶
https://example.com/schemas/common#/$defs/count/minimum¶
이 정보는 동적 범위가 참조를 지나가지 않았거나, 스키마가 자신의 "$id"로 절대 URI를 선언하지 않은 경우에만 생략될 수 있습니다.¶
이 정보에 대한 JSON 키는 "absoluteKeywordLocation"입니다.¶
검증 중인 인스턴스 안의 JSON 값 위치입니다. 값은 JSON 포인터로 표현되어야 합니다.¶
이 정보에 대한 JSON 키는 "instanceLocation"입니다.¶
검증에 의해 생성되는 오류 또는 애너테이션입니다.¶
오류의 경우, 메시지의 구체적인 문구는 이 명세에서 정의하지 않습니다. 구현이 이를 제공해야 합니다.¶
애너테이션의 경우, 애너테이션을 생성하는 각 키워드가 그 형식을 지정합니다. 기본적으로 이는 키워드의 값입니다.¶
실패한 검증에 대한 JSON 키는 "error"이고, 성공한 검증에 대해서는 "annotation"입니다.¶
두 계층 구조의 경우, 이 속성은 중첩된 오류와 애너테이션을 담습니다.¶
실패한 검증에서 중첩 결과에 대한 JSON 키는 "errors"이고, 성공한 검증에서는 "annotations"입니다. 중첩 결과를 가진 키워드도 로컬 오류나 애너테이션을 가질 수 있으므로 복수형임에 유의하십시오.¶
출력은 "valid"라는 이름의 불리언 속성을 포함하는 객체여야 합니다. 결과에 대한 추가 정보가 필요한 경우, 출력은 아래 설명처럼 "errors" 또는 "annotations"도 포함해야 합니다.¶
이 예제들에서는 다음 스키마와 인스턴스를 사용합니다.¶
{
"$id": "https://example.com/polygon",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"point": {
"type": "object",
"properties": {
"x": { "type": "number" },
"y": { "type": "number" }
},
"additionalProperties": false,
"required": [ "x", "y" ]
}
},
"type": "array",
"items": { "$ref": "#/$defs/point" },
"minItems": 3
}
[
{
"x": 2.5,
"y": 1.3
},
{
"x": 1,
"z": 6.7
}
]
¶
이 인스턴스는 검증에 실패하고 오류를 생성하지만, 애너테이션을 생성하는 통과 스키마의 예를 추론하는 것은 간단합니다.¶
구체적으로, 생성될 오류는 다음과 같습니다:¶
이러한 예에 표시된 오류 메시지 문구는 이 명세의 요구 사항이 아님에 유의하십시오. 구현은 대상 독자에 맞춘 오류 메시지를 작성하거나, 사용자가 자신의 메시지를 작성할 수 있는 템플릿 메커니즘을 제공하는 것이 좋습니다.¶
가장 단순한 경우, "valid" 유효 속성에 대한 불리언 결과만 충족하면 됩니다.¶
{
"valid": false
}
¶
이 형식에서는 오류나 애너테이션이 반환되지 않으므로, 구현은 결과가 결정되는 즉시 실패 또는 성공을 반환하도록 단락 논리를 사용하는 것이 권장됩니다. 예를 들어, "anyOf" 키워드가 다섯 개의 하위 스키마를 포함하고 두 번째가 통과한다면, 나머지 세 개를 검사할 필요가 없습니다. 논리는 단순히 성공으로 반환할 수 있습니다.¶
"Basic" 구조는 출력 단위의 평면 목록입니다.¶
{
"valid": false,
"errors": [
{
"keywordLocation": "",
"instanceLocation": "",
"error": "A subschema had errors."
},
{
"keywordLocation": "/items/$ref",
"absoluteKeywordLocation":
"https://example.com/polygon#/$defs/point",
"instanceLocation": "/1",
"error": "A subschema had errors."
},
{
"keywordLocation": "/items/$ref/required",
"absoluteKeywordLocation":
"https://example.com/polygon#/$defs/point/required",
"instanceLocation": "/1",
"error": "Required property 'y' not found."
},
{
"keywordLocation": "/items/$ref/additionalProperties",
"absoluteKeywordLocation":
"https://example.com/polygon#/$defs/point/additionalProperties",
"instanceLocation": "/1/z",
"error": "Additional property 'z' found but was invalid."
},
{
"keywordLocation": "/minItems",
"instanceLocation": "",
"error": "Expected at least 3 items but found 2"
}
]
}
¶
"Detailed" 구조는 스키마를 기반으로 하며, 사람과 기계 모두에게 더 읽기 쉬울 수 있습니다. 구조가 이런 방식으로 구성되면 오류들 사이의 연관성이 더 분명해집니다. 예를 들어, 누락된 "y" 속성과 추가된 "z" 속성이 모두 인스턴스의 같은 위치에서 비롯되었다는 사실은 "Basic" 구조에서는 즉시 명확하지 않습니다. 계층 구조에서는 그 상관관계를 더 쉽게 식별할 수 있습니다.¶
다음 규칙은 결과 객체의 구성을 지배합니다:¶
분기 노드는 오류 메시지나 애너테이션을 요구하지 않습니다.¶
{
"valid": false,
"keywordLocation": "",
"instanceLocation": "",
"errors": [
{
"valid": false,
"keywordLocation": "/items/$ref",
"absoluteKeywordLocation":
"https://example.com/polygon#/$defs/point",
"instanceLocation": "/1",
"errors": [
{
"valid": false,
"keywordLocation": "/items/$ref/required",
"absoluteKeywordLocation":
"https://example.com/polygon#/$defs/point/required",
"instanceLocation": "/1",
"error": "Required property 'y' not found."
},
{
"valid": false,
"keywordLocation": "/items/$ref/additionalProperties",
"absoluteKeywordLocation":
"https://example.com/polygon#/$defs/point/additionalProperties",
"instanceLocation": "/1/z",
"error": "Additional property 'z' found but was invalid."
}
]
},
{
"valid": false,
"keywordLocation": "/minItems",
"instanceLocation": "",
"error": "Expected at least 3 items but found 2"
}
]
}
¶
"Verbose" 구조는 스키마의 구조와 정확히 일치하는 완전히 구현된 계층 구조입니다. 이 구조는 오류의 위치가 중요한 폼 생성 및 검증에서 활용됩니다.¶
이것과 "Detailed" 구조의 주된 차이는 모든 결과가 반환된다는 점입니다. 여기에는 그렇지 않으면 제거될 하위 스키마 검증 결과 (예: 실패한 검증에 대한 애너테이션, `not` 키워드 안의 성공한 검증 등)가 포함됩니다. 이 때문에, 각 노드도 해당 노드의 검증 결과를 나타내는 `valid` 속성을 가지는 것이 권장됩니다.¶
이 출력 구조는 상당히 커질 수 있으므로, 간결성을 위해 여기에는 더 작은 예제가 제공됩니다. 위 예제의 전체 출력 구조 URI는 다음과 같습니다: https://json-schema.org/draft/2020-12/output/verbose-example.¶
// schema
{
"$id": "https://example.com/polygon",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"validProp": true,
},
"additionalProperties": false
}
// instance
{
"validProp": 5,
"disallowedProp": "value"
}
// result
{
"valid": false,
"keywordLocation": "",
"instanceLocation": "",
"errors": [
{
"valid": true,
"keywordLocation": "/type",
"instanceLocation": ""
},
{
"valid": true,
"keywordLocation": "/properties",
"instanceLocation": ""
},
{
"valid": false,
"keywordLocation": "/additionalProperties",
"instanceLocation": "",
"errors": [
{
"valid": false,
"keywordLocation": "/additionalProperties",
"instanceLocation": "/disallowedProp",
"error": "Additional property 'disallowedProp' found but was invalid."
}
]
}
]
}
¶
편의를 위해, 구현이 생성한 출력을 검증하기 위한 JSON 스키마가 제공되었습니다. 그 URI는 다음과 같습니다: https://json-schema.org/draft/2020-12/output/schema.¶
스키마와 인스턴스는 모두 JSON 값입니다. 따라서 RFC 8259 [RFC8259]에 정의된 모든 보안 고려 사항이 적용됩니다.¶
인스턴스와 스키마는 둘 다 신뢰할 수 없는 제3자가 작성하여 공개 인터넷 서버에 배포하는 경우가 많습니다. 검증기는 스키마에 대한 파싱과 검증이 과도한 시스템 리소스를 소비하지 않도록 주의해야 합니다. 검증기는 무한 루프에 빠져서는 안 됩니다.¶
악의적인 당사자는 구현이 매우 큰 값의 복사본을 애너테이션으로 반복해서 수집하게 할 수 있습니다. 구현은 이러한 시나리오에서 과도한 시스템 리소스 소비를 방지해야 합니다.¶
서버는 악의적인 당사자가 기존 또는 매우 유사한 "$id"를 가진 스키마를 업로드하여 기존 스키마의 기능을 변경할 수 없도록 보장해야 합니다.¶
개별 JSON 스키마 어휘도 자체 보안 고려 사항을 가질 수 있습니다. 자세한 내용은 해당 명세를 참조하십시오.¶
스키마 작성자는 "$comment" 내용에 주의해야 합니다. 악의적인 구현이 명세를 위반하여 이를 최종 사용자에게 표시하거나, 그러한 동작이 기대되는 경우에도 이를 제거하지 않을 수 있기 때문입니다.¶
악의적인 스키마 작성자는 "$comment" 안에 실행 가능한 코드나 다른 위험한 자료를 넣을 수 있습니다. 구현은 "$comment" 내용을 파싱하거나 그 내용에 기반하여 어떤 조치를 취해서도 안 됩니다.¶
JSON 스키마를 위한 제안 MIME 미디어 유형은 다음과 같이 정의됩니다:¶
JSON 스키마 전용 미디어 유형을 필요로 하는 JSON 스키마 인스턴스를 위한 제안 MIME 미디어 유형은 다음과 같이 정의됩니다:¶
"$id"가 루트 스키마와 여러 하위 스키마를 모두 식별하는 데 사용되고, "$anchor"가 일반 이름 프래그먼트 식별자를 정의하는 데 사용되는 다음 스키마를 생각해 보십시오.¶
{
"$id": "https://example.com/root.json",
"$defs": {
"A": { "$anchor": "foo" },
"B": {
"$id": "other.json",
"$defs": {
"X": { "$anchor": "bar" },
"Y": {
"$id": "t/inner.json",
"$anchor": "bar"
}
}
},
"C": {
"$id": "urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f"
}
}
}
¶
다음 URI 인코딩된 JSON 포인터 [RFC6901](루트 스키마 기준)에 있는 스키마들은 다음 기준 URI를 가지며, 위의 5절 및 9.2.1절에 따라 나열된 URI 중 어느 것으로든 식별될 수 있습니다.¶
참고: URI의 프래그먼트 부분이 그것을 정식 또는 비정식으로 만드는 것은 아닙니다. 오히려 (어떤 프래그먼트든 포함한 전체 URI의 일부로) 사용된 기준 URI가 결과 전체 URI의 정식 성격을 결정합니다. 여러 "정식" URI가 있습니까? 이것이 잠재적으로 혼란스러울 수 있음을 인정하며, 추가 설명은 JSON 포인터 프래그먼트와 내장된 스키마 리소스 (9.2.1절) 섹션에 있는 CREF를 읽어 보시기 바랍니다. ¶
참조("$ref")가 어떻게 그리고 어디에 나타나는지를 기준으로 스키마 문서를 재배열하기 위한 다양한 도구가 만들어졌습니다. 이 부록은 어떤 사용 사례와 조치가 이 명세를 준수하는지 논의합니다.¶
함께 사용되도록 의도된 스키마 리소스 집합은 각각 자체 스키마 문서에 둘 수도 있고, 모두 같은 스키마 문서에 둘 수도 있으며, 그 사이의 어떤 문서 그룹화 단위로도 구성할 수 있습니다.¶
다양한 종류의 참조 제거를 수행하는 많은 도구가 존재합니다. 그 일반적인 사례는 모든 참조를 그 파일 안에서 해석할 수 있는 단일 파일을 생성하는 것입니다. 이는 보통 배포를 단순화하거나, JSON 스키마 라이브러리의 여러 호출이 많은 리소스를 추적하고 로드하지 않아도 되도록 코딩을 단순화하기 위해 수행됩니다.¶
모든 정적 참조(예: "$ref")가 정식 리소스 URI를 기준으로 하여 URI로 해석되는 URI-reference를 사용하고, 모든 스키마 리소스가 자신의 루트 스키마의 "$id"로 absolute-URI를 가지는 한, 이 변환은 안전하고 되돌릴 수 있게 수행될 수 있습니다.¶
이러한 조건이 충족되면, 각 외부 리소스는 리소스의 스키마 객체들 사이의 어떤 참조도 깨뜨리지 않고, 검증이나 애너테이션 결과의 어떤 측면도 변경하지 않은 채 "$defs" 아래로 복사될 수 있습니다. "$defs" 아래의 스키마 이름은 각각 고유하다고 가정하면 동작에 영향을 주지 않습니다. 내장된 리소스의 정식 URI에 나타나지 않기 때문입니다.¶
모든 참조를 제거하고 단일 스키마 문서를 생성하려는 시도는, 모든 경우에 원래 형태와 동일한 동작을 가진 스키마를 생성하지는 않습니다.¶
"$ref"가 이제 다른 키워드와 마찬가지로 취급되고, 같은 스키마 객체 안에 다른 키워드가 허용되므로, 모든 경우에 비재귀 "$ref" 제거를 완전히 지원하려면 비교적 복잡한 스키마 조작이 필요할 수 있습니다. 안전한 "$ref" 제거 변환 집합을 결정하거나 제공하는 것은 이 명세의 범위를 벗어납니다. 이는 스키마 구조뿐만 아니라 의도된 사용 방식에도 의존하기 때문입니다.¶
각 노드가 어떤 유형의 "data" 필드도 가질 수 있는 단순한 재귀 트리 구조를 설명하는 다음 두 스키마를 생각해 보십시오. 첫 번째 스키마는 다른 인스턴스 속성을 허용하고 무시합니다. 두 번째 스키마는 더 엄격하며 "data"와 "children" 속성만 허용합니다. "data"를 "daat"로 잘못 철자한 예제 인스턴스도 함께 표시되어 있습니다.¶
// tree schema, extensible
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/tree",
"$dynamicAnchor": "node",
"type": "object",
"properties": {
"data": true,
"children": {
"type": "array",
"items": {
"$dynamicRef": "#node"
}
}
}
}
// strict-tree schema, guards against misspelled properties
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/strict-tree",
"$dynamicAnchor": "node",
"$ref": "tree",
"unevaluatedProperties": false
}
// instance with misspelled field
{
"children": [ { "daat": 1 } ]
}
¶
이 두 스키마를 로드하면, 각 스키마에 존재하는 "node"라는 이름의 "$dynamicAnchor"("#"가 없다는 점에 유의하십시오. 이는 단지 이름일 뿐입니다)를 확인하게 되며, 그 결과 다음 전체 스키마 URI가 만들어집니다:¶
또한 JSON 스키마 구현은 이러한 프래그먼트가 "$dynamicAnchor"로 생성되었다는 사실을 추적합니다.¶
"strict-tree" 스키마를 인스턴스에 적용하면, "$ref"를 따라 "tree" 스키마로 이동하고, 그 "children" 하위 스키마를 검사한 뒤, "items" 하위 스키마 안에서 "$dynamicRef": "#node"를 찾습니다 (URI 프래그먼트 구문을 위한 "#"에 유의하십시오). 그 참조는 "https://example.com/tree#node"로 해석되며, 이는 "$dynamicAnchor"로 생성된 프래그먼트를 가진 URI입니다. 따라서 참조를 따라가기 전에 동적 범위를 검사해야 합니다.¶
이 시점에서 동적 경로는 "#/$ref/properties/children/items/$dynamicRef"이며, 동적 범위는 (가장 바깥쪽 범위에서 가장 안쪽 범위까지) 다음을 포함합니다:¶
일반 이름 프래그먼트를 찾고 있으며, 이는 스키마 리소스 안의 어디에서든 정의될 수 있으므로, JSON 포인터 프래그먼트는 이 검사와 관련이 없습니다. 이는 해당 프래그먼트를 제거하고 연속된 중복을 제거하여 다음을 생성할 수 있음을 의미합니다:¶
이 경우 가장 바깥쪽 리소스에도 "$dynamicAnchor"로 정의된 "node" 프래그먼트가 있습니다. 따라서 "$dynamicRef"를 "https://example.com/tree#node"로 해석하는 대신, "https://example.com/strict-tree#node"로 해석합니다.¶
이런 방식으로 "tree" 스키마의 재귀는 인스턴스 루트에만 "strict-tree"를 적용하고 인스턴스 자식에는 "tree"를 적용하는 대신, "strict-tree"의 루트로 재귀합니다.¶
이 예제는 두 "$dynamicAnchor"가 각 스키마의 같은 위치, 구체적으로는 리소스 루트 스키마에 있음을 보여줍니다. 일반 이름 프래그먼트는 JSON 구조와 독립적이므로, 하나 또는 두 노드 스키마 객체가 "$defs" 아래로 이동하더라도 동일하게 작동합니다. 동적 참조를 해석하는 방법을 알려 주는 것은 JSON 구조의 어떤 상관관계가 아니라 일치하는 "$dynamicAnchor" 값입니다.¶
어휘 작성자는 어휘가 광범위한 사용을 의도하고 다른 어휘와 결합될 가능성이 있다면 키워드 이름 충돌을 피하도록 주의해야 합니다. JSON 스키마는 공식적인 네임스페이스 시스템을 제공하지 않지만, 키워드 이름을 제한하지도 않으므로 임의의 수의 네임스페이스 접근 방식을 허용합니다.¶
어휘는 서로를 기반으로 만들 수 있습니다. 예를 들어 다른 어휘의 키워드 동작과 관련하여 자신의 키워드 동작을 정의하거나, 다른 어휘의 키워드를 허용 가능한 값의 제한된 또는 확장된 집합과 함께 사용할 수 있습니다. 이러한 모든 어휘 재사용이 기반이 되는 어휘와 호환되는 새 어휘를 만들어 내는 것은 아닙니다. 어휘 작성자는 어떤 수준의 호환성이 기대되는지, 있다면 이를 명확히 문서화해야 합니다.¶
메타 스키마 작성자는 같은 키워드에 대해 충돌하는 구문이나 의미를 정의하는 여러 어휘를 결합하기 위해 "$vocabulary"를 사용해서는 안 됩니다. 의미 충돌은 일반적으로 스키마 검증을 통해 감지할 수 없으므로, 구현이 그러한 충돌을 감지할 것으로 기대되지 않습니다. 충돌하는 어휘가 선언되면, 결과 동작은 정의되지 않습니다.¶
어휘 작성자는 해당 어휘의 키워드에 대한 예상 사용을 자체적으로 검증하는 메타 스키마를 제공해야 합니다. 그러한 메타 스키마는 추가 키워드를 금지하지 않는 것이 좋으며, Core 어휘의 어떤 키워드도 금지해서는 안 됩니다.¶
메타 스키마 작성자는 각 어휘의 메타 스키마를 "allOf" (10.2.1.1절) 키워드를 사용하여 참조하는 것이 권장됩니다. 다만 특정 사용 사례에는 메타 스키마를 구성하는 다른 메커니즘이 적절할 수 있습니다.¶
메타 스키마의 재귀적 성격 때문에 "$dynamicAnchor" 및 "$dynamicRef" 키워드는 기존 메타 스키마를 확장하는 데 특히 유용합니다. 이는 Validation 메타 스키마를 확장하는 JSON Hyper-Schema 메타 스키마에서 볼 수 있습니다.¶
메타 스키마는 선언된 어휘와 연결된 메타 스키마가 설명하는 것 이상으로, 어떤 어휘에도 존재하지 않는 키워드를 설명하는 것을 포함하여 추가 제약을 부과할 수 있습니다. 이를 통해 어휘의 하위 집합으로 사용을 제한하고, 재사용을 의도하지 않은 로컬 정의 키워드를 검증할 수 있습니다.¶
그러나 메타 스키마는 자신이 선언하는 어떤 어휘와도 모순되어서는 안 됩니다. 예를 들어 어휘가 기대하는 것과 다른 JSON 유형을 요구하는 경우가 그렇습니다. 결과 동작은 정의되지 않습니다.¶
로컬 사용을 의도하고 임의의 구현에서 어휘 지원을 테스트할 필요가 없는 메타 스키마는 "$vocabulary"를 완전히 생략해도 안전합니다.¶
이 메타 스키마는 Core 및 Applicator 어휘를 확장 어휘와 함께 명시적으로 선언하고, 그 메타 스키마들을 "allOf"로 결합합니다. 해당 어휘의 키워드만 설명하는 확장 어휘의 메타 스키마는 주요 예제 메타 스키마 뒤에 표시되어 있습니다.¶
주요 예제 메타 스키마는 구현하기 특히 복잡한 "unevaluated"로 접두된 키워드를 금지하여 Unevaluated 어휘의 사용도 제한합니다. 이는 다른 어휘가 정의한 의미나 키워드 집합을 변경하지 않습니다. 단지 이 메타 스키마를 사용하는 스키마가 "unevaluated"로 접두된 키워드를 사용하려고 하면 이 메타 스키마에 대한 검증에 실패하도록 보장할 뿐입니다.¶
마지막으로, 이 메타 스키마는 어떤 어휘에도 속하지 않는 키워드 "localKeyword"의 구문을 설명합니다. 아마도 이 메타 스키마의 구현자와 사용자는 "localKeyword"의 의미를 이해할 것입니다. JSON 스키마는 어휘 밖에서 키워드 의미를 표현하는 어떤 메커니즘도 정의하지 않으므로, 이해되는 특정 환경을 제외하고는 사용하기에 적합하지 않습니다.¶
이 메타 스키마는 일반 사용을 위해 여러 어휘를 결합합니다.¶
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/meta/general-use-example",
"$dynamicAnchor": "meta",
"$vocabulary": {
"https://json-schema.org/draft/2020-12/vocab/core": true,
"https://json-schema.org/draft/2020-12/vocab/applicator": true,
"https://json-schema.org/draft/2020-12/vocab/validation": true,
"https://example.com/vocab/example-vocab": true
},
"allOf": [
{"$ref": "https://json-schema.org/draft/2020-12/meta/core"},
{"$ref": "https://json-schema.org/draft/2020-12/meta/applicator"},
{"$ref": "https://json-schema.org/draft/2020-12/meta/validation"},
{"$ref": "https://example.com/meta/example-vocab"}
],
"patternProperties": {
"^unevaluated": false
},
"properties": {
"localKeyword": {
"$comment": "Not in vocabulary, but validated if used",
"type": "string"
}
}
}
¶
이 메타 스키마는 단일 확장 어휘만 설명합니다.¶
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/meta/example-vocab",
"$dynamicAnchor": "meta",
"$vocabulary": {
"https://example.com/vocab/example-vocab": true,
},
"type": ["object", "boolean"],
"properties": {
"minDate": {
"type": "string",
"pattern": "\d\d\d\d-\d\d-\d\d",
"format": "date",
}
}
}
¶
위에 보인 것처럼, 일반 사용 메타 스키마의 "allOf"에서 참조되는 각 단일 어휘 메타 스키마가 대응하는 어휘를 선언하더라도, 이 새 메타 스키마는 그것들을 다시 선언해야 합니다.¶
Core 및 Validation 명세가 정의한 모든 어휘를 결합하는 표준 메타 스키마와, 그 명세들이 정의한 모든 어휘뿐 아니라 Hyper-Schema 명세도 결합하는 표준 메타 스키마는 추가적인 복잡한 조합을 보여 줍니다. 이러한 메타 스키마의 URI는 각각 Validation 및 Hyper-Schema 명세에서 찾을 수 있습니다.¶
일반 사용 메타 스키마는 "minDate"의 구문을 검증할 수 있지만, "minDate"의 의미론적 의미 뒤에 있는 논리를 정의하는 것은 어휘입니다. 의미를 이해하지 못하면(이 예에서는 인스턴스 값이 스키마에서 키워드 값으로 제공된 날짜와 같거나 그 이후의 날짜여야 한다는 것), 구현은 구문적 사용만 검증할 수 있습니다. 이 경우 이는 날짜 형식의 문자열인지 검증한다는 의미입니다("format"이 순수하게 애너테이션으로 기능할 때에도 검증되도록 "pattern"을 사용하는 것으로, Validation 명세 [json-schema-validation]에 설명되어 있습니다).¶
참조의 존재는 검증 결과에 투명할 것으로 기대되지만, 코드 생성기나 UI 렌더러 같은 생성적 사용 사례에서는 참조를 의미론적으로 중요하다고 여기는 경우가 많습니다.¶
이러한 사용 사례별 의미를 명시적으로 만들기 위한 모범 사례는, "$ref" 같은 참조 키워드와 나란히 같은 스키마 객체 안에서 사용할 애너테이션 키워드를 만드는 것입니다.¶
예를 들어, 다음은 코드 생성기가 참조 대상이 별개의 클래스로 간주되어야 하는지, 그리고 그 클래스들이 어떻게 관련되는지를 결정하기 위한 가상의 키워드입니다. 이 예제는 오직 설명 목적일 뿐이며, 실제 기능하는 코드 생성 키워드를 제안하려는 의도가 아님에 유의하십시오.¶
{
"allOf": [
{
"classRelation": "is-a",
"$ref": "classes/base.json"
},
{
"$ref": "fields/common.json"
}
],
"properties": {
"foo": {
"classRelation": "has-a",
"$ref": "classes/foo.json"
},
"date": {
"$ref": "types/dateStruct.json",
}
}
}
¶
여기서 이 스키마는 일종의 객체 지향 클래스를 나타냅니다. "allOf"의 첫 번째 참조는 기본 클래스로 표시됩니다. 두 번째 참조에는 클래스 관계가 지정되지 않았으므로, 코드 생성기는 참조가 없는 것처럼 대상의 정의를 이 정의와 결합해야 한다는 의미입니다.¶
속성을 보면, "foo"는 객체 합성으로 표시되지만 "date" 속성은 그렇지 않습니다. 이는 별개의 클래스의 인스턴스라기보다 하위 필드를 가진 단순한 필드입니다.¶
이러한 사용 방식은 애너테이션이 참조와 같은 객체 안에 있을 것을 요구하며, 그 참조는 참조로 인식 가능해야 합니다.¶
JSON 스키마의 초기 초안 작업에 기여한 Gary Court, Francis Galiegue, Kris Zyp, 그리고 Geraint Luff에게 감사드립니다.¶
문서에 제출물과 패치를 제공한 Jason Desrosiers, Daniel Perrett, Erik Wilde, Evgeny Poberezkin, Brad Bowman, Gowry Sankar, Donald Pipowitch, Dave Finlay, Denis Laxalde, Phil Sturgeon, Shawn Silverman, 그리고 Karen Etheridge에게 감사드립니다.¶
이 섹션은 Internet-Draft 상태를 벗어나기 전에 제거될 예정입니다.¶