インターネット技術タスクフォース (IETF) A. Wright 編集
インターネットドラフト
意図されたステータス:参考情報 H. Andrews 編集
有効期限:2020年3月20日
B. Hutton 編集
ウェルカム・サンガー研究所
G. Dennis
2019年9月17日

JSON スキーマ:JSON ドキュメント記述のためのメディアタイプ
draft-handrews-json-schema-02

要約

JSON スキーマは、JSON データの構造を記述するための JSON ベースのフォーマットであるメディアタイプ "application/schema+json" を定義します。JSON スキーマは、JSON ドキュメントがどのようなものであるべきか、そこから情報を抽出する方法、およびそれとのやり取り方法を規定します。"application/json" ドキュメントで提供できる範囲を超えて、"application/schema+json" との機能豊富な統合をさらに提供するメディアタイプ "application/schema-instance+json" があります。

読者への注意

このドラフトの課題リストは、<https://github.com/json-schema-org/json-schema-spec/issues> で確認できます。

詳細については、<https://json-schema.dokyumento.jp/> を参照してください。

フィードバックを提供するには、この課題トラッカー、ホームページに記載されている連絡方法、またはドキュメント編集者へのメールを使用してください。

このメモのステータス

このインターネットドラフトは、BCP 78 および BCP 79 の規定に完全に準拠して提出されています。

インターネットドラフトは、インターネット技術タスクフォース (IETF) の作業文書です。他のグループもインターネットドラフトとして作業文書を配布することがあることに注意してください。現在のインターネットドラフトのリストは、https://datatracker.ietf.org/drafts/current/ にあります。

インターネットドラフトは最大6ヶ月間有効なドラフト文書であり、いつでも他の文書によって更新、置換、または廃止される可能性があります。「進行中の作業」以外に、インターネットドラフトを参照資料として使用したり、引用したりすることは適切ではありません。

このインターネットドラフトは、2020年3月20日に期限切れになります。

著作権表示

Copyright (c) 2019 IETF Trust および文書の著者として特定された個人。全著作権所有。

この文書は、BCP 78 およびこの文書の公開日に有効なIETF文書に関するIETFトラストの法的規定(https://trustee.ietf.org/license-info)の対象となります。これらの文書をよく確認してください。これらは、この文書に関するあなたの権利と制限を説明しています。この文書から抽出されたコードコンポーネントには、トラストの法的規定のセクション4.eに記載されているように、簡素化されたBSDライセンステキストを含める必要があり、簡素化されたBSDライセンスに記載されているように、保証なしで提供されます。


目次

1. はじめに

JSON スキーマは、JSON データの構造を定義するための JSON メディアタイプです。JSON スキーマは、JSON データの検証、ドキュメント化、ハイパーリンクナビゲーション、およびインタラクション制御を定義することを目的としています。

この仕様では、別の JSON スキーマへの参照による参照、JSON スキーマ参照の逆参照、使用されているボキャブラリの指定、および期待される出力の定義など、JSON スキーマのコア用語とメカニズムを定義しています。

他の仕様では、検証、リンク、アノテーション、ナビゲーション、およびインタラクションに関するアサーションを実行するボキャブラリを定義しています。

2. 表記法と用語

このドキュメント内のキーワード「MUST」、「MUST NOT」、「REQUIRED」、「SHALL」、「SHALL NOT」、「SHOULD」、「SHOULD NOT」、「RECOMMENDED」、「MAY」、「OPTIONAL」は、RFC 2119 に記載されているように解釈されます。

このドキュメント内の用語「JSON」、「JSON テキスト」、「JSON 値」、「メンバー」、「要素」、「オブジェクト」、「配列」、「数値」、「文字列」、「ブール値」、「true」、「false」、「null」は、RFC 8259 に定義されているように解釈されます。

3. 概要

このドキュメントは、JSON データを記述するための JSON スキーマを識別するための新しいメディアタイプ "application/schema+json" を提案しています。また、追加の統合機能を提供するためのさらなるオプションのメディアタイプ "application/schema-instance+json" も提案しています。JSON スキーマ自体は JSON ドキュメントです。これと関連する仕様では、作成者がいくつかの方法で JSON データを記述できるキーワードを定義しています。

JSON スキーマは、キーワードを使用して JSON インスタンスに対する制約を主張したり、それらのインスタンスに追加情報を注釈付けたりします。追加のキーワードを使用して、より複雑な JSON データ構造にアサーションと注釈を適用したり、何らかの条件に基づいて適用したりします。

再利用を容易にするために、キーワードをボキャブラリに編成できます。ボキャブラリは、キーワードのリストとその構文とセマンティクスで構成されます。

JSON スキーマは、追加のボキャブラリを定義するか、またはより非公式に、ボキャブラリ以外の追加のキーワードを定義することによって拡張できます。認識されない個々のキーワードは無視されますが、認識されないボキャブラリに関する動作は、使用されているボキャブラリを宣言するときに制御できます。

このドキュメントでは、実装でサポートされる必要があるコアボキャブラリを定義しており、無効にすることはできません。そのキーワードには、それぞれ「$」文字が接頭辞として付けられており、その必須の性質が強調されています。このボキャブラリは "application/schema+json" メディアタイプの機能に不可欠であり、他のボキャブラリのロードをブートストラップするために使用されます。

さらに、このドキュメントでは、サブスキーマを条件付きで適用するため、およびオブジェクトと配列の内容にサブスキーマを適用するための推奨ボキャブラリを定義しています。これらのスキーマがアサーション検証、アノテーション、またはその両方を目的としている場合でも、非自明な JSON インスタンスのスキーマを作成するには、このボキャブラリまたはそれと非常に似たボキャブラリが必要です。必須のコアボキャブラリの一部ではありませんが、最大の相互運用性のために、この追加のボキャブラリはこのドキュメントに含まれており、その使用を強く推奨します。

構造検証やハイパーメディアアノテーションなどの目的のための追加の語彙は、他のドキュメントで定義されています。

4. 定義

4.1. JSONドキュメント

JSONドキュメントは、application/jsonメディアタイプで記述される情報リソース(一連のオクテット)です。

JSONスキーマでは、定義するデータモデルのために、「JSONドキュメント」、「JSONテキスト」、「JSON値」という用語は互換性があります。

JSONスキーマはJSONドキュメントに対してのみ定義されています。ただし、JSONスキーマのデータモデルに従って解析または処理できるドキュメントやメモリ構造は、CBORなどのメディアタイプを含め、JSONスキーマに対して解釈できます。

4.2. インスタンス

スキーマが適用されるJSONドキュメントは、「インスタンス」と呼ばれます。

4.2.1. インスタンスデータモデル

JSONスキーマは、データモデルに従ってドキュメントを解釈します。このデータモデルに従って解釈されたJSON値は、「インスタンス」と呼ばれます。

インスタンスは6つのプリミティブ型のいずれかで、型に応じてさまざまな値が可能です。

null
JSONの「null」プロダクション
boolean
JSONの「true」または「false」プロダクションからの「true」または「false」の値
object
JSONの「object」プロダクションからの、文字列をインスタンスにマッピングするプロパティの順序付けられていない集合
array
JSONの「array」プロダクションからのインスタンスの順序付きリスト
number
JSONの「number」プロダクションからの、任意精度の10進数
string
JSONの「string」プロダクションからのUnicodeコードポイントの文字列

空白とフォーマットに関する懸念事項(データモデル内で等しい数値の異なる字句表現など)は、JSONスキーマの範囲外です。このような字句表現の違いを扱うことを望むJSONスキーマの語彙は、元のJSON表現のUnicode文字が利用可能であることに依存するのではなく、データモデル内でフォーマットされた文字列を正確に解釈するためのキーワードを定義する必要があります。

オブジェクトは同じキーを持つ2つのプロパティを持つことができないため、単一のオブジェクト内で同じキー(「string」プロダクション)を持つ2つのプロパティ(「member」プロダクション)を定義しようとするJSONドキュメントの動作は未定義です。

JSONスキーマの語彙は、独自の拡張型システムを自由に定義できることに注意してください。これは、ここで定義されているコアデータモデル型と混同しないでください。「integer」は、キーワードの値として定義する語彙にとって妥当な型ですが、データモデルは整数と他の数値を区別しません。

4.2.2. インスタンスメディアタイプ

JSONスキーマは、「application/json」ドキュメントと、 "+json"構造化構文サフィックスを使用するメディアタイプと完全に連携するように設計されています。

スキーマの処理に役立つ機能の一部は、各メディアタイプ、つまりメディアタイプパラメータとURIフラグメント識別子の構文とセマンティクスによって定義されます。これらの機能は、それぞれコンテンツネゴシエーションと、インスタンス内の特定の場所のURIの計算に役立ちます。

この仕様では、「application/schema-instance+json」メディアタイプを定義して、インスタンス作成者がこれらの目的でパラメータとフラグメント識別子を最大限に活用できるようにします。

4.2.3. インスタンスの等価性

2つのJSONインスタンスは、データモデルに従って同じ型で同じ値を持つ場合に限り、等しいと言われます。具体的には、これは次のことを意味します。

この定義には、配列の長さが同じであること、オブジェクトが同じ数のメンバーを持っていること、オブジェクトのプロパティは順序付けられていないこと、同じキーを持つ複数のプロパティを定義する方法がないこと、単なるフォーマットの違い(インデント、コンマの配置、末尾のゼロ)は重要ではないことが含まれています。

4.3. JSONスキーマドキュメント

JSONスキーマドキュメント、または単にスキーマとは、インスタンスを記述するために使用されるJSONドキュメントです。スキーマ自体はインスタンスとして解釈できますが、「application/schema-instance+json」ではなく「application/schema+json」メディアタイプを常に指定する必要があります。「application/schema+json」メディアタイプは、「application/schema-instance+json」によって提供されるメディアタイプパラメータとフラグメント識別子の構文とセマンティクスのスーパーセットを提供するために定義されています。

JSONスキーマは、オブジェクトまたはブール値である必要があります。

4.3.1. JSONスキーマオブジェクトとキーワード

インスタンスに適用されるオブジェクトのプロパティは、キーワード、またはスキーマキーワードと呼ばれます。一般的に、キーワードは次の4つのカテゴリのいずれかに分類されます。

識別子
スキーマの正規URIを設定したり、基本URIの決定方法を変更したりすることで、スキーマの識別を制御します。
アサーション
インスタンスに適用されるとブール値の結果を生成します。
アノテーション
アプリケーションで使用するためにインスタンスに情報を添付します。
アプリケータ
1つ以上のサブスキーマをインスタンスの特定の場所に適用し、その結果を組み合わせたり変更したりします。
予約済み場所
結果は直接影響しませんが、相互運用性を確保するために特定の目的のための場所を予約します。

キーワードは複数のカテゴリに分類される場合がありますが、アプリケータはサブスキーマの結果に基づいてアサーションの結果を生成する必要があります。サブスキーマとは別に追加の制約を定義するべきではありません。

このドキュメントとその付属物以外で定義されている拡張キーワードは、他の動作も自由に定義できます。

JSONスキーマには、スキーマキーワードではないプロパティを含めることができます。不明なキーワードは無視する必要があります。

空のスキーマは、プロパティがないか、不明なプロパティのみを持つJSONスキーマです。

4.3.2. ブール値のJSONスキーマ

ブール値のスキーマ値「true」と「false」は、インスタンス値に関係なく、常にそれ自体をアサーションの結果として生成する自明なスキーマです。アノテーションの結果は生成されません。

これらのブール値のスキーマは、スキーマ作成者の意図を明確にし、スキーマ処理の最適化を容易にするために存在します。(「not」がこのドキュメントで定義されているサブスキーマアプリケーション語彙の一部である場合)次のスキーマオブジェクトとまったく同じ動作をします。

true
空のスキーマ{}のように、常に検証に合格します。
false
スキーマ{"not": {}}のように、常に検証に失敗します。

空のスキーマオブジェクトは明確ですが、「false」スキーマには多くの可能な同等物があります。ブール値を使用すると、人間の読者と実装の両方にとって意図が明確になります。

4.3.3. スキーマ語彙

スキーマ語彙、または単に語彙とは、キーワード、その構文、およびそのセマンティクスの集合です。語彙は一般的に特定の目的を中心に構成されています。検証、ハイパーメディア、ユーザーインターフェースの生成などのJSONスキーマのさまざまな用途には、さまざまな語彙の集合が関与します。

語彙はJSONスキーマでの再利用の主要な単位です。スキーマ作成者は、スキーマを処理するために必要な語彙またはオプションの語彙を示すことができます。語彙はメタスキーマでURIによって識別されるため、一般的な実装では拡張機能を読み込んで、以前は不明だった語彙をサポートできます。キーワードはどの語彙にも含まれていなくてもサポートできますが、個々のキーワードの使用を示す同様のメカニズムはありません。

4.3.4. メタスキーマ

それ自体がスキーマを記述するスキーマは、メタスキーマと呼ばれます。メタスキーマは、JSONスキーマを検証し、使用している語彙を指定するために使用されます。

通常、メタスキーマは一連の語彙を指定し、それらの語彙の構文に準拠するスキーマを検証します。ただし、メタスキーマと語彙は別々にされており、メタスキーマは語彙の仕様が要求するよりも厳密にまたは緩やかにスキーマの適合性を検証できるようにします。メタスキーマは、正式な語彙の一部ではない追加のキーワードを記述および検証することもできます。

4.3.5. ルートスキーマとサブスキーマとリソース

JSONスキーマのリソースとは、正規に絶対URIで識別されるスキーマです。

ルートスキーマとは、問題のJSONドキュメント全体を構成するスキーマです。ルートスキーマは常にスキーマリソースであり、URIはセクション8.2.1で説明されているように決定されます。

一部のキーワードはそれ自体がスキーマを使用するため、JSONスキーマをネストできます。

{
    "title": "root",
    "items": {
        "title": "array item"
    }
}

                        

この例では、「array item」というタイトルのスキーマはサブスキーマであり、「root」というタイトルのスキーマはルートスキーマです。

ルートスキーマと同様に、サブスキーマはオブジェクトまたはブール値です。

セクション8.2.2で説明されているように、JSONスキーマドキュメントには複数のJSONスキーマリソースを含めることができます。修飾せずに使用する場合、「ルートスキーマ」という用語はドキュメントのルートスキーマを指します。場合によっては、リソースルートスキーマについて説明します。リソースのルートスキーマはその最上位のスキーマオブジェクトであり、リソースをスタンドアロンのJSONスキーマドキュメントに抽出する場合もドキュメントルートスキーマになります。

5. フラグメント識別子

[RFC6839]のセクション3.1に従って、任意の+jsonメディアタイプに対して指定されたフラグメント識別子の構文とセマンティクスは、「application/json」に対して指定されたものと同じである必要があります。(このドキュメントの公開時点では、「application/json」に対して定義されているフラグメント識別構文はありません。)

さらに、「application/schema+json」メディアタイプは、プレーン名とJSONポインタの2つのフラグメント識別子構造をサポートします。「application/schema-instance+json」メディアタイプは、JSONポインタの1つのフラグメント識別子構造をサポートします。

URIフラグメント識別子としてのJSONポインタの使用については、RFC 6901で説明されています。「application/schema+json」は2つのフラグメント識別子構文をサポートしているため、空文字列を含むJSONポインタ構文と一致するフラグメント識別子は、JSONポインタフラグメント識別子として解釈する必要があります。

W3Cのフラグメント識別子のベストプラクティスに従って、「application/schema+json」のプレーン名フラグメント識別子は、ローカルに名前が付けられたスキーマを参照するために予約されています。JSONポインタ構文と一致しないすべてのフラグメント識別子は、プレーン名フラグメント識別子として解釈する必要があります。

「application/schema+json」ドキュメント内のプレーン名フラグメント識別子の定義と参照は、"$anchor"キーワードセクションで指定されています。

6. 一般的な考慮事項

6.1. JSON値の範囲

インスタンスは、JSONで定義されているとおり、任意の有効なJSON値にすることができます。JSON Schemaは型に制限を課しません。JSON Schemaは、nullなど、あらゆるJSON値を記述できます。

6.2. プログラミング言語の独立性

JSON Schemaはプログラミング言語に依存せず、データモデルで記述されているすべての値をサポートします。ただし、一部の言語やJSONパーサーでは、JSONで記述できるすべての値をメモリ内に表現できない場合があります。

6.3. 数学的整数

一部のプログラミング言語とパーサーでは、浮動小数点数と整数の内部表現が異なります。

一貫性を保つために、整数JSON数値は小数部を含めてエンコードしないでください。

6.4. 正規表現

キーワードは、制約を表すために正規表現を使用したり、インスタンス値を正規表現に制限したりすることができます。これらの正規表現は、ECMA 262、セクション15.10.1で説明されている正規表現の方言に従って有効である必要があります。

さらに、正規表現構成要素のサポートには大きなばらつきがあるため、スキーマ作成者は、次の正規表現トークンに限定する必要があります。

最後に、実装は正規表現の先頭と末尾のどちらにもアンカーされていないものとして扱う必要があります。つまり、たとえばパターン「es」は「expression」に一致します。

6.5. JSON Schemaの拡張

追加のスキーマキーワードとスキーマボキャブラリは、どのエンティティでも定義できます。明示的な合意がない限り、スキーマ作成者は、そのようなサポートを明示的に文書化していない実装で、これらの追加のキーワードとボキャブラリがサポートされると期待してはなりません。実装は、サポートしていないキーワードを無視する必要があります。

実装は、直接サポートしていないボキャブラリのハンドラーを登録またはロードする機能を提供できます。そのようなハンドラーの登録と実装の正確なメカニズムは、実装依存です。

7. キーワードの動作

JSON Schemaのキーワードは、いくつかの一般的な動作カテゴリに分類されます。アサーションは、インスタンスが制約を満たしていることを検証し、ブール値の結果を生成します。注釈は、アプリケーションが自由に使用できる情報を添付します。適用子は、インスタンスの一部にサブスキーマを適用し、その結果を組み合わせます。

拡張キーワードは、これらのカテゴリ内に留まる必要があります。特に注釈は非常に柔軟であることに注意してください。複雑な動作は、通常、注釈データに基づいてアプリケーションに委任する方が、スキーマキーワードとして直接実装するよりも優れています。ただし、拡張キーワードは、特殊な目的のために他の動作を定義できます。

インスタンスをスキーマに対して評価するには、インスタンス内の適切な場所にスキーマ内のすべてのキーワードを処理する必要があります。通常、適用子キーワードは、適用子がない(したがってサブスキーマもない)スキーマオブジェクトに到達するまで処理されます。インスタンス内の適切な場所は、スキーマオブジェクト内のアサーションキーワードと注釈キーワードに対して評価され、その結果は適用子のルールに従って親スキーマに収集されます。

親スキーマオブジェクトの評価は、すべてのサブスキーマが評価された後に完了できますが、状況によっては、アサーションの結果によって評価が短絡される場合があります。注釈を収集している場合、アサーションの結果の短絡は、アサーションの結果をさらに変更できないものも含めて、すべてのサブスキーマを注釈の収集のために調べる必要があるため、不可能です。

7.1. 字句スコープと動的スコープ

ほとんどのJSON Schemaキーワードは単独で評価できますが、多くても同じスキーマオブジェクト内の隣接するキーワードの値または結果を考慮する必要がありますが、より複雑な動作を持つものもあります。

キーワードの字句スコープは、オブジェクトと配列の入れ子になったJSONデータ構造によって決定されます。そのような最大のスコープは、スキーマドキュメント全体です。最小のスコープは、サブスキーマのない単一のスキーマオブジェクトです。

キーワードは、URI参照などの部分的な値で定義でき、別のURI参照または完全なURIなどの別の値に対して解決する必要があります。これは、JSONドキュメントの字句構造を通じて見つけることができます。"$id"コアキーワードと"base" JSONハイパー・スキーマキーワードはこのような動作の例です。さらに、この仕様の"$ref"と"$recursiveRef"はこのように値を解決しますが、それ以降の値の解決方法を変更しません。

"$schema"などのキーワードの中には、スキーマドキュメント全体の字句スコープに適用されるものがあり、そのため、スキーマリソースのルートスキーマにのみ表示する必要があります。

他のキーワードは、スキーマの評価中に存在する動的スコープを考慮することがあります。これは、通常、インスタンスドキュメントと共に考慮されます。最も外側の動的スコープは、処理が開始されるスキーマドキュメントのルートスキーマです。このルートスキーマから特定のキーワードまでのパス(解決されている可能性のある"$ref"と"$recursiveRef"キーワードを含む)は、キーワードの「検証パス」と見なされます。[CREF1]それとも、ルートスキーマではない場合でも、処理が開始されるスキーマオブジェクトにするべきでしょうか?これは、「$recursiveAnchor」がルートスキーマでのみ許可されているが、処理がサブスキーマで開始される場合にいくつかの影響を与えます。

参照キーワードが検出されるまで、字句スコープと動的スコープは一致しています。参照キーワードに従うと、処理が1つの字句スコープから別の字句スコープに移行しますが、動的スコープの観点からは、参照に従うことは、値として存在するサブスキーマに降りるのと変わりありません。動的スコープを通じて情報を解決するその参照の向こう側のキーワードは、ローカルに字句的に囲んでいる親ではなく、参照の元の側を動的親と見なします。

動的スコープの概念は、主に"$recursiveRef"と"$recursiveAnchor"で使用され、高度な機能と見なされ、追加のキーワードを定義する際には注意して使用する必要があります。また、エラーと収集された注釈を報告する場合にも表示されます。これは、同じ字句スコープを異なる動的スコープで繰り返し再訪できる可能性があるためです。このような場合、エラーまたは注釈を生成した動的パスをユーザーに通知することが重要です。

7.2. キーワードの相互作用

キーワードの動作は、サブスキーマおよび/または隣接するキーワードの注釈結果に基づいて定義できます。このようなキーワードは、循環依存関係をもたらしてはなりません。キーワードは、同じスキーマオブジェクトに別のキーワードが存在するかどうかによって動作を変更できます。

7.3. デフォルトの動作

欠落しているキーワードは、偽のアサーション結果を生成してはならず、注釈結果を生成してはならず、その動作定義の一部として他のスキーマを評価してはいけません。ただし、欠落しているキーワードは注釈に寄与しないため、注釈結果の欠如は、他のキーワードの動作を間接的に変更する可能性があります。

場合によっては、欠落しているキーワードのアサーション動作は、特定の値によって生成されるものと同一であり、キーワードの定義は、既知の場合、そのような値を指摘する必要があります。ただし、デフォルトの動作を生成する値が存在する場合は注釈結果を生成する可能性がありますが、デフォルトの動作は注釈を生成してはなりません。

注釈の収集は、計算とメモリの両方の点でかなりのコストを追加する可能性があるため、実装はこれを省略できます。注釈の結果に依存するアサーションまたは適用子の動作を持つことが実装によって既知のキーワードは、同じ動作を生成する代替実装が利用できる場合を除いて、エラーとして扱う必要があります。このような種類のキーワードは、適切な場合は、妥当な代替アプローチを説明する必要があります。このアプローチは、このドキュメントの"additionalItems"と"additionalProperties"キーワードによって示されています。

7.4. 識別子

識別子は、スキーマの標準URIを設定するか、参照でのそのようなURIの解決方法、またはその両方に影響を与えます。このドキュメントで定義されているコアボキャブラリは、特に"$id"を最も重要なものとして、いくつかの識別キーワードを定義しています。

標準スキーマURIは、インスタンスを処理している間は変更してはなりませんが、URI参照の解決に影響を与えるキーワードは、実行時にのみ完全に決定される動作を持つ可能性があります。

カスタム識別子キーワードは可能ですが、ボキャブラリ設計者は、コアキーワードの機能を妨げないように注意する必要があります。たとえば、この仕様の"$recursiveAnchor"キーワードは、そのURI解決の効果を一致する"$recursiveRef"キーワードに限定し、「$ref」はそのまま残します。

7.5. 適用子

適用子を使用すると、単一のスキーマオブジェクトでは実現できないよりも複雑なスキーマを作成できます。スキーマドキュメントに対するインスタンスの評価は、完全なインスタンスドキュメントにルートスキーマを適用することから始まります。そこから、適用子として知られるキーワードを使用して、適用される追加のスキーマを決定します。そのようなスキーマは、現在の場所に、または子場所にインプレースで適用できます。

適用するスキーマは、キーワードの値のすべてまたは一部を構成するサブスキーマとして存在する場合があります。あるいは、適用子は、同じスキーマドキュメント内または異なるスキーマドキュメント内の他の場所にあるスキーマを参照する場合もあります。そのような参照されたスキーマを識別するメカニズムは、キーワードによって定義されます。

適用子キーワードは、サブスキーマまたは参照されたスキーマのブール値アサーションの結果が変更および/または組み合わされて、適用子のブール値の結果が生成される方法も定義します。適用子は、サブスキーマのアサーション結果に任意のブール論理演算を適用できますが、独自のアサーション条件を導入してはなりません。

注釈の結果は、各注釈キーワードで指定されたルールに従って組み合わせられます。

7.5.1. 参照されたスキーマと参照するスキーマ

7.5節「適用子キーワード」で述べられているように、適用子キーワードは、適用するスキーマをその適用子の値のサブスキーマとして含めるのではなく、適用するスキーマを参照する可能性があります。このような状況では、適用されるスキーマは**参照スキーマ**と呼ばれ、適用子キーワードを含むスキーマは**参照元スキーマ**と呼ばれます。

ルートスキーマとサブスキーマは、スキーマ文書内でのスキーマの位置に基づいた静的な概念であるのに対し、参照スキーマと参照元スキーマは動的なものです。インスタンスをスキーマに対して評価する際に、異なるスキーマのペアが、様々な参照スキーマと参照元スキーマの配置にあることが分かります。

"$ref"など、参照による適用子の場合、参照スキーマはスキーマ文書の字句スコープの静的解析によって決定できます。一方、"$recursiveRef"や"$recursiveAnchor"などは動的スコープを使用するため、インスタンスを含むスキーマの評価プロセスでなければ解決できません。

7.6. アサーション

JSON Schemaは、JSON文書に対する制約をアサート(主張)するために使用できます。アサーションは、成功するか失敗するかのいずれかになります。このアプローチは、制約への適合性を検証したり、制約を満たすために必要なものを文書化したりするために使用できます。

JSON Schemaの実装は、インスタンスをスキーマのアサーションに対して評価する際に、単一のブール値の結果を生成します。

インスタンスは、スキーマに存在するアサーションのみを失敗させることができます。

7.6.1. アサーションとインスタンスのプリミティブ型

ほとんどのアサーションは、特定のプリミティブ型内の値のみを制約します。インスタンスの型がキーワードの対象となる型ではない場合、インスタンスはアサーションに準拠していると見なされます。

たとえば、付属の検証ボキャブラリの"maxLength"キーワードは、特定の文字列(長すぎる文字列)のみを無効とします。インスタンスが数値、ブール値、null、配列、またはオブジェクトの場合、このアサーションに対して有効です。

この動作により、複数のプリミティブ型である可能性のあるインスタンスでキーワードをより簡単に使用できます。付属の検証ボキャブラリには、インスタンスを1つ以上のプリミティブ型に独立して制限できる"type"キーワードも含まれています。これにより、特定の長さの文字列またはnull値のいずれかを返す可能性のある関数などのユースケースを簡潔に表現できます。

{
    "type": ["string", "null"],
    "maxLength": 255
}

                        

"maxLength"がインスタンスの型を文字列に制限する場合、記述されている例では実際にはnull値を許可しないため、これを表現することははるかに面倒になります。各キーワードは、特に明示的に指定されていない限り、個別に評価されるため、"maxLength"がインスタンスを文字列に制限する場合でも、"type"に"null"を含めても有用な効果はありません。

7.7. アノテーション

JSON Schemaは、インスタンスがアノテーションを含むスキーマオブジェクトとそのすべての親スキーマオブジェクトに対して検証されるたびに、インスタンスに情報をアノテーションすることができます。情報は単純な値でも、インスタンスの内容に基づいて計算された値でもかまいません。

アノテーションは、インスタンス内の特定の場所に添付されます。多くのサブスキーマを単一の場所に適用できるため、アノテーションキーワードは、異なる値を持つキーワードの複数の適用可能な出現に関する特別な処理を指定する必要があります。

アサーションの結果とは異なり、アノテーションデータは幅広い形式を取ることができ、アプリケーションが必要に応じて使用できます。JSON Schemaの実装は、アプリケーションに代わって収集された情報を使用することは想定されていません。

特に指定がない限り、アノテーションキーワードのアノテーションの値は、キーワードの値です。ただし、他の動作も可能です。たとえば、JSON Hyper-Schemaの"links"キーワードは、インスタンスデータに基づいて値を生成する複雑なアノテーションです。

アサーションでは「ショートサーキット」評価が可能ですが、アノテーションの収集には、全体的なアサーションの結果を変更できない場合でも、インスタンスの場所に適用されるすべてのスキーマを調べる必要があります。唯一の例外は、検証に失敗したスキーマオブジェクトのサブスキーマはスキップできることです(失敗したスキーマのアノテーションは保持されません)。

7.7.1. アノテーションの収集

アノテーションは、アノテーション収集動作を明示的に定義するキーワードによって収集されます。ブールスキーマはキーワードを使用しないため、アノテーションを生成できないことに注意してください。

収集されたアノテーションには、次の情報が含まれている**必要があります**。

同じキーワードが複数のスキーマの場所から同じインスタンスの場所に値を添付し、アノテーションがそのような値を組み合わせるプロセスを定義する場合、組み合わせられた値もインスタンスの場所に関連付けられている**必要があります**。この仕様で説明されているアノテーション情報を含む出力形式は、この要件を満たしています。

7.7.1.1. 複数の値の区別

アプリケーションは、値に寄与したスキーマの場所に基づいて、複数のアノテーション値のどれを使用するかを決定できます。これは柔軟な使用方法を可能にすることを目的としています。スキーマの場所を収集することで、そのような使用が容易になります。

たとえば、検証仕様のアノテーションとアサーションを使用する次のスキーマを考えてみます。

いくつかの行は、明確にするために改行されています。

{
    "title": "Feature list",
    "type": "array",
    "items": [
        {
            "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
        }
    }
}

                            

この例では、機能Aと機能Bの両方が、再利用可能な"enabledToggle"スキーマを使用しています。そのスキーマは"title"、"description"、"default"のアノテーションを使用しますが、複数の値の処理に関する特別な動作は定義されていません。したがって、アプリケーションは、機能Aの追加の"default"値と機能Bの追加の"description"値をどのように処理するかを決定する必要があります。

アプリケーションプログラマとスキーマ作成者は、使用方法について合意する必要があります。この例では、最も具体的な"default"値が使用され、追加の、より一般的な"default"値は黙って無視されると仮定します。また、すべての"description"テキストが使用され、最も一般的なものから始まり、最も具体的なもので終わると仮定します。これには、スキーマ作成者が、このように組み合わせたときに機能する記述を作成する必要があります。

アプリケーションは、スキーマの場所のパスを使用して、どの値がどれであるかを判断できます。機能の直近の"enabled"プロパティスキーマの値はより具体的である一方、"$ref"で参照される再利用可能なスキーマの下の値はより一般的です。スキーマの場所のパスは、各値が"$ref"を通過することによって見つかったかどうかを示します。

したがって、機能Aはtrueのデフォルト値を使用し、機能Bはnullの一般的なデフォルト値を使用します。機能Aには"enabledToggle"スキーマからの一般的な説明のみが含まれ、機能Bは、その説明と、null値の解釈方法を説明するローカルに定義された説明も使用します。

異なるアプリケーションが採用する可能性のある他の妥当なアプローチがあることに注意してください。たとえば、アプリケーションは、スキーマの場所に関わらず、"default"の2つの異なる値の存在をエラーと見なす可能性があります。

7.7.1.2. アノテーションとアサーション

falseのアサーション結果を生成するスキーマオブジェクトは、独自のキーワードからでも、サブスキーマのキーワードからでも、アノテーション結果を生成しては**なりません**。

全体的なスキーマの結果には、他のスキーマの場所から収集されたアノテーションがまだ含まれている可能性があることに注意してください。次のスキーマを検討してください。

{
    "oneOf": [
        {
            "title": "Integer Value",
            "type": "integer"
        },
        {
            "title": "String Value",
            "type": "string"
        }
    ]
}

                            

そしてインスタンス"This is a string"の場合、「Integer Value」というタイトルのアノテーションは、そのスキーマオブジェクトの型のアサーションが失敗するため破棄されます。インスタンスが文字列型のアサーションに合格するため、「String Value」というタイトルのアノテーションは保持されます。

7.7.1.3. アノテーションと適用子

適用子キーワードは、独自の注釈結果を定義する可能性に加えて、サブスキーマまたは参照スキーマで収集された注釈を集約します。注釈値を集約する規則は、各注釈キーワードによって定義され、アサーション結果の組み合わせに使用されるロジックの影響を直接受けません。

7.8. 予約済み場所

4番目のキーワードのカテゴリは、スキーマ作成者にとって興味深い再利用可能なコンポーネントまたはデータを保持する場所を単に予約するものであり、再利用には適していません。これらのキーワードは、検証やアノテーションの結果に影響を与えません。コアボキャブラリにおける目的は、特定の目的に場所を利用できるようにし、拡張キーワードによって再定義されないようにすることです。

これらのキーワードは、8.2.4.4節で説明されているように、結果に直接影響を与えませんが、再利用可能なスキーマの場所を予約する認識されない拡張キーワードは、特定の状況で参照と望ましくない相互作用を起こす可能性があります。

8. JSON Schemaコアボキャブラリ

このセクションで宣言されているキーワード(すべて"$"で始まる)は、JSON Schemaコアボキャブラリを構成します。これらのキーワードは、複数の文書に分割されたスキーマやメタスキーマを含む、任意のスキーマまたはメタスキーマを処理するために必要であるか、または保証された相互運用性を必要とする目的のためにキーワードを予約するために存在します。

さらにボキャブラリを処理するためにブートストラップするために、コアボキャブラリは常に必須であると見なす**必要があります**。使用中のボキャブラリを宣言するために"$vocabulary"キーワードを使用するメタスキーマは、必須であることを示すtrueの値を持つコアボキャブラリを明示的にリストする**必要があります**。

このボキャブラリ(およびこのボキャブラリのみ)に対するfalse値の動作は未定義であり、"$vocabulary"が存在するがコアボキャブラリが含まれていない場合の動作も未定義です。ただし、実装がこれらのケースを検出し、発生したときにエラーを発生させることを**推奨**します。メタスキーマがコアをオプションで使用すると宣言することは意味がありません。

"$vocabulary"を使用しないメタスキーマは、そのURIがtrueの値で存在する場合と同様に、コアボキャブラリを必要とするものと見なす**必要があります**。

コアボキャブラリの現在のURIは次のとおりです。<https://json-schema.dokyumento.jp/draft/2019-09/vocab/core>

対応するメタスキーマの現在のURIは次のとおりです。<https://json-schema.dokyumento.jp/draft/2019-09/meta/core>

「$」プレフィックスはコアボキャブラリに対して正式には予約されていませんが、将来的な衝突を避けるために、拡張キーワード(ボキャブラリ内またはそれ以外)は「$」以外の文字で始めることを推奨します。

8.1. メタスキーマとボキャブラリ

メタスキーマとボキャブラリの2つの概念を使用して、実装に対してスキーマの解釈方法を知らせます。すべてのスキーマにはメタスキーマがあり、「$schema」キーワードを使用して宣言できます。

メタスキーマは2つの目的を果たします。

使用中のボキャブラリの宣言
「$vocabulary」キーワードは、メタスキーマに表示されると、そのメタスキーマを参照するスキーマで使用できるボキャブラリを宣言します。ボキャブラリは、キーワードのセマンティクスとその一般的な構文を定義します。
有効なスキーマ構文の説明
スキーマは、そのメタスキーマに対して正常に検証されなければなりません。これは、使用可能なキーワードの構文を制約します。記述されている構文は、宣言されたボキャブラリと互換性があることが期待されます。非互換な構文を記述することは可能ですが、そのようなメタスキーマは役に立たない可能性が高いでしょう。

メタスキーマはボキャブラリとは別に存在することで、ボキャブラリをさまざまな方法で組み合わせたり、メタスキーマの作成者が特定のキーワードを禁止したり、開発およびテストサイクルで行われる可能性のある、通常よりも厳格な構文検証を実行したりすることを可能にします。各ボキャブラリは通常、ボキャブラリのキーワードのみからなるメタスキーマを識別します。

メタスキーマの作成は、JSON スキーマの高度な使用方法であるため、メタスキーマ機能の設計では、シンプルさよりも柔軟性が重視されています。

8.1.1. 「$schema」キーワード

「$schema」キーワードは、JSON スキーマの機能セット識別子として、そしてそれ自体がJSON スキーマであるリソースの識別子として使用されます。これは、この特定の機能セットに対して記述された有効なスキーマのセットを記述します。

このキーワードの値は、URI(スキームを含む)でなければならず、このURIは正規化されなければなりません。現在のスキーマは、このURIによって識別されるメタスキーマに対して有効でなければなりません。

このURIが取得可能なリソースを識別する場合、そのリソースはメディアタイプ「application/schema+json」である必要があります。

「$schema」キーワードは、リソースルートスキーマで使用することを推奨します。リソースサブスキーマには表示できません。ルートスキーマに存在しない場合、結果の動作は実装によって定義されます。

単一のドキュメントに複数のスキーマリソースが存在する場合、すべてのスキーマリソースは「$schema」に対して同じ値を持つ必要があります。「$schema」の値が同じスキーマドキュメント内で異なる場合の結果は、実装によって定義されます。[CREF2]同じドキュメントで複数の「$schema」キーワードを使用すると、機能セットと動作がドキュメント内で変更されることを意味します。これにより、まだ明確に定義されていない多くの実装上の問題を解決する必要があります。したがって、「$schema」をルートスキーマでのみ使用するパターンは、スキーマ作成のベストプラクティスとして残る可能性が高いですが、実装の動作は将来のドラフトで改訂または自由化される可能性があります。 [CREF3]埋め込まれたスキーマリソースに対して行われた例外は、後でこの仕様で説明するように、複数のスキーマリソースを単一のスキーマドキュメントにバンドルする際に、内容を変更する必要がないようにするためです。

このプロパティの値は、このドキュメントおよび他のドキュメント、ならびに他の当事者によって、別途定義されています。

8.1.2. 「$vocabulary」キーワード

「$vocabulary」キーワードは、メタスキーマで使用され、そのメタスキーマによって記述されるスキーマで使用できるボキャブラリを識別します。また、実装がスキーマを正常に処理するために必要なボキャブラリを理解する必要があるという意味で、各ボキャブラリが必要かどうかを示すためにも使用されます。

このキーワードの値はオブジェクトでなければなりません。オブジェクトのプロパティ名はURI(スキームを含む)でなければならず、このURIは正規化されなければなりません。プロパティ名として表示される各URIは、特定のキーワードセットとそのセマンティクスを識別します。

URIはURLでもかまいませんが、取得可能なリソースの性質は現在未定義であり、将来の使用のために予約されています。ボキャブラリ作成者は、text/htmlやtext/plainなどのヒューマンリーダブルなメディアタイプで、ボキャブラリ仕様のURLをボキャブラリURIとして使用できます。[CREF4]ボキャブラリドキュメントは今後のドラフトに追加される可能性があります。現時点では、キーワードセットの識別が十分であると見なされています。これは、メタスキーマ検証と合わせて、現在の「ボキャブラリ」の動作方法です。将来のボキャブラリドキュメント形式はJSONドキュメントとして指定されるため、その間はtext/htmlなどの非JSON形式を使用しても、将来のあいまいさは発生しません。

オブジェクトプロパティの値はブール値でなければなりません。値がtrueの場合、ボキャブラリを認識しない実装は、「$schema」を使用してこのメタスキーマを宣言するスキーマの処理を拒否しなければなりません。値がfalseの場合、ボキャブラリを認識しない実装は、そのようなスキーマの処理を続行する必要があります。

6.5に従って、認識されないキーワードは無視する必要があります。これは、認識されないボキャブラリによって定義されたキーワードについても同様です。ボキャブラリで定義されている認識されないキーワードと、どのボキャブラリにも属していないキーワードを区別することは、現在できません。

「$vocabulary」キーワードは、メタスキーマとして使用するスキーマドキュメントのルートスキーマで使用することを推奨します。サブスキーマには表示できません。

「$vocabulary」キーワードは、メタスキーマとして処理されていないスキーマドキュメントでは無視する必要があります。これにより、バリデータがMによって宣言されたボキャブラリを理解する必要なしに、メタスキーマMをそのメタスキーマM'に対して検証できます。

8.1.2.1. 既定のボキャブラリ

「$vocabulary」が存在しない場合、実装は、参照するスキーマの「$schema」キーワードのURI値から認識される場合、メタスキーマに基づいて動作を決定できます。これは、ボキャブラリが存在する前に、(Hyper-Schemaの使用など)動作が認識されていた方法です。

スキーマによって参照されるメタスキーマが認識されない場合、または存在しない場合、動作は実装によって定義されます。実装がスキーマの処理を続行する場合、コアボキャブラリの使用を想定しなければなりません。実装が特定の目的に構築されている場合、その目的のために最も関連性の高いすべてのボキャブラリの使用を想定する必要があります。

たとえば、バリデータである実装は、この仕様とコンパニオン検証仕様のすべてのボキャブラリの使用を想定する必要があります。

8.1.2.2. ボキャブラリの非継承性

「$vocabulary」の処理制限により、「$ref」または同様のキーワードを使用して他のメタスキーマを参照するメタスキーマは、それらの他のメタスキーマのボキャブラリ宣言を自動的に継承しないことに注意してください。そのような宣言はすべて、メタスキーマとして使用する各スキーマドキュメントのルートに繰り返す必要があります。これは、メタスキーマの例で示されています。[CREF5]この要件により、実装は各メタスキーマの単一箇所ですべてのボキャブラリの要件情報を取得できます。スキーマの拡張性により、参照によってより細かいメタスキーマを組み合わせる無限の可能性があるため、実装がすべて可能性を予測し、参照されたメタスキーマでボキャブラリを検索することを要求することは、過度の負担となります。

8.1.3. メタスキーマとボキャブラリURIの更新

エラーを修正するために、仕様ドラフト間で更新されたボキャブラリとメタスキーマのURIを公開できます。実装は、この仕様ドラフトの後、次のドラフトの前に日付が付けられたURIを考慮して、ここに記載されているものと同じ構文とセマンティクスを示す必要があります。

8.1.4. メタスキーマの検出

実装は、他のスキーマの「$schema」キーワードによってそのようなものとして識別されたために検査されている場合、スキーマをメタスキーマとして認識しなければなりません。これは、単一のスキーマドキュメントが、通常のスキーマと見なされる場合と、メタスキーマと見なされる場合があることを意味します。

独自のメタスキーマであるスキーマを検査する場合、実装が通常のスキーマとして処理を開始すると、それらのルールに従って処理されます。ただし、独自の「$schema」値をチェックした結果、2回目にロードされると、メタスキーマとして扱われます。したがって、同じドキュメントは1つのセッションの間に両方で処理されます。

実装は、実装固有の目的(一般的に使用されるメタスキーマを事前にロードし、そのボキャブラリのサポート要件を事前にチェックするなど)のために、スキーマをメタスキーマとして明示的に渡すことを許可できます。メタスキーマの作成者は、そのような機能が実装間で相互運用可能であることを期待してはなりません。

8.2. ベースURI、アンカー、およびデリファレンシング

広大なエコシステム内のスキーマを区別するために、スキーマはURIによって識別され、そのURIを指定することで他のスキーマへの参照を埋め込むことができます。

いくつかのキーワードは、相対的なURI参照、または相対URI参照を作成するために使用される値を受け入れることができます。これらのキーワードの場合、参照を解決するためにベースURIを確立する必要があります。

8.2.1. 初期ベースURI

RFC3986セクション5.1は、ドキュメントの既定のベースURIを決定する方法を定義しています。

参考までに、スキーマの初期ベースURIは、それがネットワークの場所、ローカルファイルシステム、または既知のスキームのいずれかのURIによって識別可能なその他の状況であったかどうかにかかわらず、それが発見されたURIです。

スキーマドキュメントが「$id」(コンテンツに埋め込まれている)を使用して明示的なベースURIを定義していない場合、ベースURIはRFC 3986セクション5に従って決定されます。

ソースが不明な場合、またはソースにURIスキームが不明な場合、RFC 3986セクション5.1.4で説明されているように、適切な実装固有の既定のURIを使用できます。実装は、想定する既定のベースURIを文書化することをお勧めします。

次のセクションで説明する「$id」キーワードがルートスキーマに存在しない限り、このベースURIはスキーマドキュメントのルートスキーマリソースの標準URIと見なされる必要があります。

8.2.2. 「$id」キーワード

「$id」キーワードは、スキーマリソースをその標準URIで識別します。

このURIは識別子であり、ネットワークロケータではないことに注意してください。ネットワークアドレス指定可能なURLの場合、スキーマは標準URIからダウンロードする必要はありません。

存在する場合、このキーワードの値は文字列でなければならず、有効なURI参照を表す必要があります。このURI参照は正規化される必要があり、絶対URI(フラグメントなし)に解決する必要があります。したがって、「$id」は空ではないフラグメントを含めることはできず、空のフラグメントを含めるべきではありません。

application/schema+jsonメディアタイプの文脈における空のフラグメントは、フラグメントのないベースURIと同じリソースを参照します。実装は、フラグメントを削除することで、空のフラグメントで終わるURIを正規化しても構いません(MAY)。しかし、スキーマ作成者は、実装間でのこの動作に依存すべきではありません(SHOULD NOT)。[CREF6]これは主に、古いメタスキーマがその$id(または以前はid)に空のフラグメントを持っているため許可されています。将来のドラフトでは、"$id"内の空のフラグメントを完全に禁止する可能性があります。

このURIは、RFC 3986セクション5.1.1のコンテンツに埋め込まれたベースURIに関する記述に従い、スキーマリソース内のキーワードにおける相対URI参照のベースURIとしても機能します。

RFC 3986セクション5.1.2のエンティティのカプセル化に関する記述に従い、サブスキーマに"$id"が存在することは、そのサブスキーマが単一のスキーマドキュメント内で別個のスキーマリソースを構成することを示します。さらに、サブスキーマの"$id"が相対URI参照である場合、その参照を解決するためのベースURIは、親スキーマリソースのURIとなります。

親スキーマオブジェクトが"$id"でリソースとして明示的に識別されていない場合、ベースURIは前のセクションで説明した手順で確立された、ドキュメント全体のURIとなります。

8.2.2.1. ルートスキーマの識別

JSONスキーマドキュメントのルートスキーマは、絶対URI(スキームを含むがフラグメントを含まない)を持つ"$id"キーワードを含めるべきです(SHOULD)。

8.2.2.2. JSONポインタフラグメントと埋め込みスキーマリソース

JSONポインタURIフラグメントはスキーマドキュメントの構造に基づいて構築されるため、埋め込みスキーマリソースとそのサブスキーマは、独自の正規URI、または包含リソースのURIに対するJSONポインタフラグメントによって識別できます。

概念的には、リンクされたスキーマリソースのセットは、各リソースがスキーマ参照で接続された個別のドキュメントであるか、1つ以上のスキーマリソースがサブスキーマとして埋め込まれた単一のドキュメントとして構造化されているかに関わらず、同じように動作するはずです。

親スキーマリソースのURIに対するJSONポインタフラグメントを含むURIは、埋め込みスキーマが別のドキュメントに移動され参照されると無効になるため、アプリケーションとスキーマは、埋め込みスキーマリソースまたはその内部の場所を識別するためにそのようなURIを使用すべきではありません(SHOULD NOT)。

別のスキーマリソースが埋め込まれている次のスキーマドキュメントを考えてみましょう。

{
  "$id": "https://example.com/foo",
  "items": {
    "$id": "https://example.com/bar",
    "additionalProperties": { }
  }
}

                            

"https://example.com/foo#/items/additionalProperties"というURIは、埋め込みリソースの"additionalProperties"キーワードのスキーマを指します。しかし、そのスキーマの正規URIは"https://example.com/bar#/additionalProperties"です。

次に、"$ref"のURI値を使用して参照によってリンクされた次の2つのスキーマリソースを考えてみましょう。

{
  "$id": "https://example.com/foo",
  "items": {
    "$ref": "bar"
  }
}

{
  "$id": "https://example.com/bar",
  "additionalProperties": { }
}

                            

ここで、"additionalProperties"サブスキーマの正規URIはまだ有効であるのに対し、"#/items/$ref"で始まるフラグメントを持つ非正規URIは何も解決されなくなっていることがわかります。

また、"https://example.com/foo#/items"はどちらの構成でも有効ですが、異なる値に解決されます。このURIは、リソースの取得URIと同様に機能するようになります。有効ではありますが、解決された値を調べ、(値がサブスキーマである場合)"$id"を使用するか、参照を解決して参照ターゲットの"$id"を使用することが望ましいです。

実装は、非正規URIによってスキーマへのアドレス指定をサポートしないことを選択しても構いません(MAY)。そのため、スキーマの相互運用性を低下させる可能性があるため、スキーマ作成者は正規URIのみを使用することを推奨します(RECOMMENDED)。[CREF7]これは、スキーマリソースが再編成された場合、1つを除くすべてが壊れやすくなるため、実装が可能なベースURIとJSONポインタフラグメントのスタック全体を追跡する必要性を回避するためです。簡単なので禁止する必要はないと主張する人もいれば、スキーマの識別を複雑にするので禁止するべきだと主張する人もいます。このトピックに関するフィードバックを歓迎します。

そのような非正規URIのさらなる例と、代わりに使用する適切な正規URIについては、付録Aに記載されています。

8.2.3. "$anchor"を使用した位置に依存しない識別子の定義

JSONポインタフラグメントを使用するには、スキーマの構造に関する知識が必要です。再利用可能なスキーマを提供することを意図してスキーマドキュメントを作成する場合は、特定の構造上の場所に結びついていないプレーンな名前フラグメントを使用する方が良い場合があります。これにより、JSONポインタ参照を更新することなく、サブスキーマを再配置できます。

"$anchor"キーワードは、そのようなフラグメントを指定するために使用されます。これは、プレーンな名前フラグメントを作成するためにのみ使用できる識別子キーワードです。

存在する場合、このキーワードの値は文字列でなければならず、文字([A-Za-z])で始まり、任意の数の文字、数字([0-9])、ハイフン("-")、アンダースコア("_")、コロン(":")、またはピリオド(".")が続く必要があります。[CREF8]アンカー文字列には"#"文字が含まれていないことに注意してください。これはURI参照ではないためです。" $anchor": "foo"は、URIで使用されると"#foo"というフラグメントになります。完全な例については下記を参照してください。

結果として得られるフラグメントが追加されるベースURIは、前のセクションで説明したように"$id"キーワードによって決定されます。同じスキーマドキュメント内の2つの"$anchor"キーワードは、異なるベースURIに適用される場合、同じ値を持つことができます。結果として得られる完全なURIは異なるためです。ただし、同じ値とベースURIを持つ2つの"$anchor"キーワードの効果は未定義です。実装は、そのような使用が検出された場合、エラーを発生させることができます(MAY)。

8.2.4. スキーマ参照

いくつかのキーワードを使用して、現在のインスタンスの場所に適用されるスキーマを参照できます。"$ref"と"$recursiveRef"は適用子キーワードであり、参照されたスキーマをインスタンスに適用します。"$recursiveRef"のURI参照値の解決のためのベースURIを制御する識別子キーワードは"$recursiveAnchor"です。

"$ref"と"$recursiveRef"の値はURI参照であるため、複数のファイルにスキーマを外部化または分割したり、自己参照を通じて再帰構造を検証したりできます。

これらのキーワードによって生成される解決済みURIは、必ずしもネットワークロケータではなく、識別子です。スキーマは、ネットワークアドレス可能なURLである場合、アドレスからダウンロードする必要はなく、実装はネットワークアドレス可能なURIに遭遇した場合にネットワーク操作を実行する必要があると想定すべきではありません(SHOULD NOT)。

8.2.4.1. "$ref"を使用した直接参照

"$ref"キーワードは、静的に識別されたスキーマを参照するために使用される適用子です。その結果は、参照されたスキーマの結果です。[CREF9]この結果の決定方法の定義は、他のキーワードが同じスキーマオブジェクト内の"$ref"と一緒に表示される可能性があることを意味します。

"$ref"プロパティの値は、URI参照である文字列でなければなりません。現在のURIベースに対して解決され、適用するスキーマのURIが生成されます。

8.2.4.2. "$recursiveRef"と"$recursiveAnchor"を使用した再帰参照

"$recursiveRef"と"$recursiveAnchor"キーワードは、拡張可能な再帰スキーマを構築するために使用されます。再帰スキーマとは、空のフラグメントURI参照("#")で識別される独自のルートへの参照を持つスキーマです。

簡単に言うと、"$recursiveRef"は、ターゲットスキーマに値がtrueの"$recursiveAnchor"が含まれている場合を除いて、"$ref"とまったく同じように動作します。その場合、新しいベースURIを決定するために動的スコープが調べられ、"$recursiveRef"のURI参照はそのベースURIに対して再評価されます。"$id"によるベースURIの変更とは異なり、"$recursiveAnchor"による変更は"$recursiveRef"が解決されるたびに計算され、他のキーワードには影響しません。

これらのキーワードを使用した例については、付録Cを参照してください。[CREF10]以前のドラフトのハイパー・スキーマ・メタスキーマとこのドラフトの大きな違いは、これらのキーワードの有用性を劇的に示しています。

8.2.4.2.1. "$recursiveRef"を使用した動的な再帰参照

"$recursiveRef"プロパティの値は、URI参照である文字列でなければなりません。これは、動的に計算されたベースURIを使用してその値を解決する、参照による適用子です。

このキーワードの動作は、値"#"に対してのみ定義されています。実装は、他の値をエラーと見なすことを選択しても構いません(MAY)。[CREF11]この制限は将来緩和される可能性がありますが、現在まで"#"の値にのみ明確なユースケースがあります。

"$recursiveRef"の値は、最初に"$ref"と同様に現在のベースURIに対して解決されます。

結果として得られたURIで識別されたスキーマについて"$recursiveAnchor"の存在が調べられ、次のセクションでそのキーワードについて説明されているように、新しいベースURIが計算されます。

最後に、"$recursiveRef"の値は、"$recursiveAnchor"に従って決定された新しいベースURIに対して解決され、最終的な解決済み参照URIが生成されます。

"$recursiveAnchor"がない場合(および存在する場合もある)、"$recursiveRef"の動作は"$ref"の動作と同じであることに注意してください。

"$ref"と同様に、このキーワードの結果は、参照されたスキーマの結果です。

8.2.4.2.2. "$recursiveAnchor"を使用した再帰の有効化

"$recursiveAnchor"プロパティの値はブール値でなければなりません。

"$recursiveAnchor"は、そのような計算を開始できる場所と終了できる場所をマークすることで、実行時に"$recursiveRef"のベースURIを動的に識別するために使用されます。このキーワードは、明示的に依存するように定義されていない限り、他のキーワードのベースURIに影響を与えるべきではありません(MUST NOT)。

trueに設定されている場合、包含スキーマオブジェクトが"$recursiveRef"のターゲットとして使用されると、値がtrueの"$recursiveAnchor"も含まれる最外部のスキーマの動的スコープを調べて、新しいベースURIが決定されます。そのスキーマのベースURIが動的ベースURIとして使用されます。

そのようなスキーマが存在しない場合、ベースURIは変更されません。

このキーワードがfalseに設定されている場合、ベースURIは変更されません。

このキーワードを省略すると、falseの値と同じ動作になります。

8.2.4.3. 無限再帰に対する保護

スキーマは、インスタンスに対して無限ループに陥るべきではありません(MUST NOT)。たとえば、2つのスキーマ"#alice"と"#bob"の両方に、互いを参照する"allOf"プロパティがある場合、単純なバリデーターはインスタンスの検証を試みる際に無限再帰ループに陥る可能性があります。スキーマは、このような無限再帰ネストを使用するべきではありません(SHOULD NOT)。その動作は未定義です。

8.2.4.4. 可能性のある非スキーマへの参照

サブスキーマオブジェクト(またはブール値)は、既知の適用子キーワード、または"$defs"など、1つ以上のサブスキーマを値として取る場所予約キーワードとの使用によって認識されます。これらのキーワードは"$defs"とこのドキュメントの標準適用子、または既知の語彙からの拡張キーワード、または実装固有のカスタムキーワードである可能性があります。

未知のキーワードの複数レベルの構造は、ネストされたサブスキーマを導入する可能性があり、それは"$id"の処理ルールに従います。したがって、そのような認識されていない構造に参照ターゲットを持つことは確実に実装できず、結果として得られる動作は未定義です。同様に、値がスキーマではないことがわかっている既知のキーワードの下にある参照ターゲットは、そのようなターゲットを検出する必要があるという負担を実装に負わせることを回避するために、未定義の動作になります。[CREF12]これらのシナリオは、HTTP経由でスキーマを取得するが、application/schema+json以外のContent-Typeを持つ応答を受信することに似ています。実装はそれをスキーマとして解釈しようと試みることはできますが、オリジンサーバーはそれが実際にそのようなものであるという保証を提供していません。したがって、それをそのようなものとして解釈することはセキュリティ上の問題があり、予測できない結果を生成する可能性があります。

「$defs」と同一の構文とセマンティクスを持つシングルレベルのカスタムキーワードは、介在する「$id」キーワードを許容しません。そのため、任意の参照ターゲットをスキーマとして使用しようとする実装下では正しく動作します。ただし、この動作は実装固有であり、相互運用性のために依存してはなりません。

8.2.4.5. 参照されたスキーマの読み込み

リモートスキーマを識別するためのURIの使用は、必ずしも何かがダウンロードされることを意味するわけではありません。代わりに、JSONスキーマ実装は、事前にどのスキーマを使用するか、およびそれらを識別するURIを理解する必要があります。

スキーマがダウンロードされる場合(たとえば、実行時までどのスキーマをダウンロードするか分からない一般的なユーザーエージェントによる場合)、ハイパーメディアの使用を参照してください。

実装は、バリデータがスキーマを信頼しているかどうかに応じて、任意のURIを任意のスキーマに関連付けるか、またはスキーマの「$id」で指定されたURIを自動的に関連付けることができる必要があります。そのようなURIとスキーマは、インスタンスを処理する前に実装に提供することも、処理中にスキーマドキュメント内に記述することもできます。付録Aに示すように、関連付けが生成されます。

スキーマは複数のURIを持つことができます(そしておそらく持つでしょう)が、1つのURIが複数のスキーマを識別する方法はありません。複数のスキーマが同じURIとして識別しようとした場合、バリデータはエラー状態を発生させる必要があります。

8.2.4.6. 逆参照

スキーマは、JSONポインタまたは「$id」によって直接指定されたURIなど、それらに与えられた任意のURIによって識別できます。「$ref」参照の逆参照には、まずその値をRFC 3986に従って現在のベースURIに対する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>`スキーマを検出した場合、現在のベースURIに対して「$id」URI参照を解決して``を形成します。

次に、実装が`<#/items>`スキーマ内を参照すると、`<#item>`参照が検出され、これが``に解決されます。これは、この同じドキュメントで定義されていることがわかっているので、自動的に使用できます。

実装が「other.json」への参照を検出した場合、これは``に解決されます。これはこのドキュメントでは定義されていません。その識別子を持つスキーマがそれ以外に実装に提供されている場合、それも自動的に使用できます。[CREF13]参照されたスキーマが不明な場合、実装は何を行う必要がありますか?自動ネットワーク逆参照が許可される状況はありますか?同一オリジンポリシーは?ユーザー設定可能なオプションは?ハイパー・スキーマによって記述される進化するAPIの場合、新しいスキーマはシステムに動的に追加されることが予想されるため、スキーマ・ドキュメントの事前読み込みを絶対的に要求することは実行可能ではありません。

8.2.5. 「$defs」を使用したスキーマの再利用

「$defs」キーワードは、スキーマ作成者が再利用可能なJSONスキーマをより一般的なスキーマにインラインで組み込む場所を予約します。このキーワードは、検証結果に直接影響を与えません。

このキーワードの値はオブジェクトである必要があります。このオブジェクトの各メンバー値は、有効なJSONスキーマである必要があります。

{
    "type": "array",
    "items": { "$ref": "#/$defs/positiveInteger" },
    "$defs": {
        "positiveInteger": {
            "type": "integer",
            "exclusiveMinimum": 0
        }
    }
}

                            

例として、正の整数制約が「$defs」内のサブスキーマである正の整数の配列を記述するスキーマを次に示します。

8.3. 「$comment」によるコメント

このキーワードは、スキーマ作成者からスキーマの閲覧者または保守担当者へのコメントを保存する場所を予約します。

このキーワードの値は文字列である必要があります。実装は、この文字列をエンドユーザーに提示してはなりません。スキーマを編集するためのツールは、このキーワードの表示と編集をサポートする必要があります。このキーワードの値は、スキーマを使用する開発者を対象としたデバッグまたはエラー出力で使用できます。

スキーマ・ボキャブラリは、ボキャブラリ・キーワードを含む任意のオブジェクト内に「$comment」を許可する必要があります。実装は、ボキャブラリがそれを明示的に禁止しない限り、「$comment」が許可されていると想定しても構いません。ボキャブラリは、この仕様で説明されているもの以外に、「$comment」の効果を指定してはなりません。

他のメディアタイプまたはプログラミング言語をapplication/schema+jsonとの間で変換するツールは、「$comment」値との間でそのメディアタイプまたはプログラミング言語のネイティブコメントを変換することを選択できます。ネイティブコメントと「$comment」プロパティの両方が存在する場合のそのような変換の動作は実装依存です。

実装は「$comment」を未知の拡張キーワードと同様に処理する必要があります。処理中の任意の時点で「$comment」値を削除しても構いません。特に、展開されたスキーマのサイズが懸念事項である場合、スキーマの短縮が可能になります。

実装は、「$comment」プロパティの存在、不在、または内容に基づいて、他のアクションを実行してはなりません。特に、「$comment」の値は注釈結果として収集してはなりません。

9. サブスキーマを適用するためのボキャブラリ

このセクションでは、他のボキャブラリの基礎として推奨される、適用キーワードのボキャブラリを定義します。

「$vocabulary」を使用しないメタスキーマは、そのURIがtrueの値で存在する場合と同様に、このボキャブラリを必要とするものとみなされる必要があります。

適用ボキャブラリとして知られるこのボキャブラリの現在のURIは次のとおりです。<https://json-schema.dokyumento.jp/draft/2019-09/vocab/applicator>

対応するメタスキーマの現在のURIは次のとおりです。<https://json-schema.dokyumento.jp/draft/2019-09/meta/applicator>

エラーを修正するために、仕様ドラフト間で更新されたボキャブラリとメタスキーマのURIを公開できます。実装は、この仕様ドラフトの後、次のドラフトの前に日付が付けられたURIを考慮して、ここに記載されているものと同じ構文とセマンティクスを示す必要があります。

9.1. キーワードの独立性

スキーマキーワードは、通常、互いの結果に影響を与えることなく、独立して動作します。

スキーマ作成者の便宜のために、このボキャブラリ内のキーワードにはいくつかの例外があります。

9.2. サブスキーマをその場で適用するためのキーワード

これらのキーワードは、親スキーマが適用されているインスタンスと同じ場所にサブスキーマを適用します。これにより、サブスキーマの結果をさまざまな方法で組み合わせたり、変更したりできます。

9.2.1. ブール論理を使用してサブスキーマを適用するためのキーワード

これらのキーワードは、サブスキーマのブールアサーション結果を組み合わせたり変更したりするための論理演算子に対応しています。注釈の収集には直接的な影響はありませんが、同じ注釈キーワードを異なる値を持つインスタンスの場所に適用できるようにします。注釈キーワードは、そのような値を組み合わせるための独自のルールを定義します。

9.2.1.1. allOf

このキーワードの値は、空でない配列である必要があります。配列の各項目は、有効なJSONスキーマである必要があります。

インスタンスは、このキーワードの値によって定義されたすべてのスキーマに対して正常に検証された場合、このキーワードに対して正常に検証されます。

9.2.1.2. anyOf

このキーワードの値は、空でない配列である必要があります。配列の各項目は、有効なJSONスキーマである必要があります。

インスタンスは、このキーワードの値によって定義された少なくとも1つのスキーマに対して正常に検証された場合、このキーワードに対して正常に検証されます。注釈が収集されている場合、すべてのサブスキーマを調べ、正常に検証された各サブスキーマから注釈が収集される必要があることに注意してください。

9.2.1.3. oneOf

このキーワードの値は、空でない配列である必要があります。配列の各項目は、有効なJSONスキーマである必要があります。

インスタンスは、このキーワードの値によって定義された正確に1つのスキーマに対して正常に検証された場合、このキーワードに対して正常に検証されます。

9.2.1.4. not

このキーワードの値は、有効なJSONスキーマである必要があります。

インスタンスは、このキーワードによって定義されたスキーマに対して正常に検証に失敗した場合、このキーワードに対して有効です。

9.2.2. サブスキーマを条件付きで適用するためのキーワード

これらのキーワードの3つは、別のサブスキーマの結果に基づいてサブスキーマの条件付き適用を実装するために連携して機能します。4番目は、特定の条件付きケースのショートカットです。

「if」、「then」、および「else」は、サブスキーマの境界を越えて互いに相互作用してはなりません。言い換えれば、「allOf」の1つのブランチの「if」は、別のブランチの「then」または「else」に影響を与えてはなりません。

存在しない場合、「if」、「then」、「else」にはデフォルトの動作がありません。特に、空のスキーマが存在する場合と同様に扱ってはならず、「if」が存在しない場合、「then」と「else」の両方が完全に無視される必要があります。

9.2.2.1. if

このキーワードの値は、有効なJSONスキーマである必要があります。

このキーワードのサブスキーマの検証結果は、全体的な検証結果に直接影響を与えません。むしろ、「then」または「else」のどちらのキーワードが評価されるかを制御します。

このキーワードのサブスキーマに対して正常に検証されたインスタンスは、存在する場合、「then」キーワードのサブスキーマ値に対しても有効である必要があります。

このキーワードのサブスキーマに対して検証に失敗したインスタンスは、存在する場合、「else」キーワードのサブスキーマ値に対しても有効である必要があります。

注釈が収集されている場合、「then」または「else」のいずれかが存在しない場合でも、通常どおりこのキーワードのサブスキーマから収集されます。

9.2.2.2. then

このキーワードの値は、有効なJSONスキーマである必要があります。

「if」が存在し、インスタンスがそのサブスキーマに対して正常に検証された場合、インスタンスがまたこのキーワードのサブスキーマに対して正常に検証された場合、このキーワードに対して検証が成功します。

このキーワードは、「if」が存在しない場合、またはインスタンスがそのサブスキーマに対して検証に失敗した場合に効果がありません。実装は、そのような場合、検証または注釈収集の目的で、このキーワードに対してインスタンスを評価してはなりません。

9.2.2.3. else

このキーワードの値は、有効なJSONスキーマである必要があります。

"if"キーワードが存在し、インスタンスがそのサブスキーマに対して検証に失敗した場合、インスタンスがこのキーワードのサブスキーマに対して検証に成功すれば、このキーワードに対する検証は成功します。

"if"キーワードが存在しない場合、またはインスタンスがそのサブスキーマに対して検証に成功した場合、このキーワードは効果を持ちません。そのような場合、実装は検証またはアノテーション収集の目的で、インスタンスをこのキーワードに対して評価してはなりません。

9.2.2.4. dependentSchemas

このキーワードは、インスタンスがオブジェクトであり、特定のプロパティを含む場合に評価されるサブスキーマを指定します。

このキーワードの値はオブジェクトである必要があります。オブジェクト内の各値は有効なJSONスキーマである必要があります。

オブジェクトキーがインスタンス内のプロパティである場合、インスタンス全体はサブスキーマに対して検証に合格する必要があります。その使用はプロパティの存在に依存します。

このキーワードを省略した場合、空のオブジェクトと同じ動作になります。

9.3. サブスキーマを子インスタンスに適用するためのキーワード

これらのキーワードのそれぞれは、サブスキーマを子インスタンス(具体的にはオブジェクトのプロパティと配列の要素)に適用し、その結果を組み合わせるためのルールを定義します。

9.3.1. 配列にサブスキーマを適用するためのキーワード

9.3.1.1. items

"items"の値は、有効なJSONスキーマ、または有効なJSONスキーマの配列のいずれかである必要があります。

"items"がスキーマの場合、配列内のすべての要素がそのスキーマに対して検証に成功すれば、検証は成功します。

"items"がスキーマの配列の場合、インスタンスの各要素が、同じ位置にあるスキーマ(存在する場合)に対して検証に成功すれば、検証は成功します。

このキーワードは、このキーワードがサブスキーマを適用した最大のインデックスをアノテーション値として生成します。 "items"がスキーマである場合など、サブスキーマがインスタンスのすべてのインデックスに適用された場合は、値をブール値のtrueにすることができます。

同じインスタンスの位置に適用された複数のスキーマからの"items"キーワードのアノテーション結果は、いずれかの値がtrueの場合に結合結果をtrueに設定し、それ以外の場合は最大の数値を保持することで結合されます。

このキーワードを省略した場合、空のスキーマと同じアサーション動作になります。

9.3.1.2. additionalItems

"additionalItems"の値は、有効なJSONスキーマである必要があります。

このキーワードの動作は、同じスキーマオブジェクト内の"items"の存在とアノテーション結果に依存します。"items"が存在し、そのアノテーション結果が数値の場合、その数値より大きいインデックスにあるすべてのインスタンス要素が"additionalItems"に対して検証に成功すれば、検証は成功します。

それ以外の場合、"items"が存在しない場合、またはそのアノテーション結果がブール値のtrueの場合、"additionalItems"は無視する必要があります。

"additionalItems"サブスキーマがインスタンス配列内の任意の位置に適用される場合、"items"の単一スキーマ動作と同様に、ブール値trueのアノテーション結果を生成します。同じインスタンスの位置に適用された任意の"additionalItems"キーワードがtrueのアノテーション値を生成した場合、これらのキーワードからの結合結果もtrueになります。

このキーワードを省略した場合、空のスキーマと同じアサーション動作になります。

実装は、"items"配列の存在とサイズを直接確認するなど、同じ効果を生む別の方法でこのキーワードを実装または最適化することを選択できます。アノテーション収集をサポートしていない実装は、そうする必要があります。

9.3.1.3. unevaluatedItems

"unevaluatedItems"の値は、有効なJSONスキーマである必要があります。

このキーワードの動作は、検証対象のインスタンスの位置に適用される隣接するキーワードのアノテーション結果に依存します。具体的には、"unevaluatedItems"キーワードに隣接する場合にそれらのキーワードから取得できる"items"と"additionalItems"からのアノテーションです。これら2つのアノテーションと"unevaluatedItems"は、すべてまたは任意の隣接するインプレース適用器キーワードからも結果として得られます。これには、このドキュメントで定義されているインプレース適用器が含まれますが、これらに限定されません。

"items"アノテーションが存在し、そのアノテーション結果が数値であり、"additionalItems"または"unevaluatedItems"アノテーションが存在しない場合、"items"アノテーションより大きいインデックスにあるすべてのインスタンス要素が"unevaluatedItems"に対して検証に成功すれば、検証は成功します。

それ以外の場合、"items"、"additionalItems"、または"unevaluatedItems"のアノテーションがブール値trueの値で存在する場合、"unevaluatedItems"は無視する必要があります。ただし、これらのアノテーションがどれも存在しない場合、"unevaluatedItems"は配列内のすべての位置に適用する必要があります。

これは、"items"、"additionalItems"、およびすべてのインプレース適用器は、このキーワードを評価する前に評価する必要があることを意味します。拡張キーワードの作者は、このキーワードの前に評価する必要があるインプレース適用器を定義してはなりません。

"unevaluatedItems"サブスキーマがインスタンス配列内の任意の位置に適用される場合、"items"の単一スキーマ動作と同様に、ブール値trueのアノテーション結果を生成します。同じインスタンスの位置に適用された任意の"unevaluatedItems"キーワードがtrueのアノテーション値を生成した場合、これらのキーワードからの結合結果もtrueになります。

このキーワードを省略した場合、空のスキーマと同じアサーション動作になります。

アノテーションを収集しない実装は、このキーワードに遭遇するとエラーを発生させる必要があります。

9.3.1.4. contains

このキーワードの値は、有効なJSONスキーマである必要があります。

配列インスタンスは、その要素の少なくとも1つが指定されたスキーマに対して有効な場合に"contains"に対して有効です。アノテーションを収集する場合、最初のマッチが見つかった後でも、サブスキーマはすべての配列要素に適用する必要があることに注意してください。これは、可能なすべてのアノテーションが収集されるようにするためです。

9.3.2. オブジェクトにサブスキーマを適用するためのキーワード

9.3.2.1. properties

"properties"の値はオブジェクトである必要があります。このオブジェクトの各値は有効なJSONスキーマである必要があります。

インスタンスとこのキーワードの値の両方に出現する各名前について、その名前の子インスタンスが対応するスキーマに対して検証に成功すれば、検証は成功します。

このキーワードのアノテーション結果は、このキーワードによって一致したインスタンスプロパティ名のセットです。同じインスタンスの位置に適用された複数のスキーマからの"properties"キーワードのアノテーション結果は、セットの和集合を取ることによって結合されます。

このキーワードを省略した場合、空のオブジェクトと同じアサーション動作になります。

9.3.2.2. patternProperties

"patternProperties"の値はオブジェクトである必要があります。このオブジェクトのプロパティ名のそれぞれは、ECMA 262正規表現ダイアレクトに従って有効な正規表現である必要があります。このオブジェクトのプロパティ値のそれぞれは有効なJSONスキーマである必要があります。

このキーワードのプロパティ名として表示される正規表現のいずれかに一致するインスタンス名について、その名前の子インスタンスが一致する正規表現に対応する各スキーマに対して検証に成功すれば、検証は成功します。

このキーワードのアノテーション結果は、このキーワードによって一致したインスタンスプロパティ名のセットです。同じインスタンスの位置に適用された複数のスキーマからの"patternProperties"キーワードのアノテーション結果は、セットの和集合を取ることによって結合されます。

このキーワードを省略した場合、空のオブジェクトと同じアサーション動作になります。

9.3.2.3. additionalProperties

"additionalProperties"の値は、有効なJSONスキーマである必要があります。

このキーワードの動作は、同じスキーマオブジェクト内の"properties"と"patternProperties"の存在とアノテーション結果に依存します。"additionalProperties"による検証は、"properties"または"patternProperties"のアノテーション結果に表示されないインスタンス名の値の子にのみ適用されます。

そのようなプロパティすべてについて、子インスタンスが"additionalProperties"スキーマに対して検証に成功すれば、検証は成功します。

このキーワードのアノテーション結果は、このキーワードのサブスキーマによって検証されたインスタンスプロパティ名のセットです。同じインスタンスの位置に適用された複数のスキーマからの"additionalProperties"キーワードのアノテーション結果は、セットの和集合を取ることによって結合されます。

このキーワードを省略した場合、空のスキーマと同じアサーション動作になります。

実装は、"properties"の名前と"patternProperties"のパターンをインスタンスプロパティセットに対して直接確認するなど、同じ効果を生む別の方法でこのキーワードを実装または最適化することを選択できます。アノテーション収集をサポートしていない実装は、そうする必要があります。

9.3.2.4. unevaluatedProperties

"unevaluatedProperties"の値は、有効なJSONスキーマである必要があります。

このキーワードの動作は、検証対象のインスタンスの位置に適用される隣接するキーワードのアノテーション結果に依存します。具体的には、"unevaluatedProperties"キーワードに隣接する場合にそれらのキーワードから取得できる"properties"、"patternProperties"、"additionalProperties"からのアノテーションです。これら3つのアノテーションと"unevaluatedProperties"は、すべてまたは任意の隣接するインプレース適用器キーワードからも結果として得られます。これには、このドキュメントで定義されているインプレース適用器が含まれますが、これらに限定されません。

"unevaluatedProperties"による検証は、検証対象のインスタンスの位置に適用される"properties"、"patternProperties"、"additionalProperties"、または"unevaluatedProperties"のアノテーション結果に表示されないインスタンス名の値の子にのみ適用されます。

そのようなプロパティすべてについて、子インスタンスが"unevaluatedProperties"スキーマに対して検証に成功すれば、検証は成功します。

これは、"properties"、"patternProperties"、"additionalProperties"、およびすべてのインプレース適用器は、このキーワードを評価する前に評価する必要があることを意味します。拡張キーワードの作者は、このキーワードの前に評価する必要があるインプレース適用器を定義してはなりません。

このキーワードのアノテーション結果は、このキーワードのサブスキーマによって検証されたインスタンスプロパティ名のセットです。同じインスタンスの位置に適用された複数のスキーマからの"unevaluatedProperties"キーワードのアノテーション結果は、セットの和集合を取ることによって結合されます。

このキーワードを省略した場合、空のスキーマと同じアサーション動作になります。

アノテーションを収集しない実装は、このキーワードに遭遇するとエラーを発生させる必要があります。

9.3.2.5. propertyNames

"propertyNames"の値は、有効なJSONスキーマである必要があります。

インスタンスがオブジェクトの場合、このキーワードは、インスタンス内のすべてのプロパティ名が提供されたスキーマに対して検証に成功するかどうかを検証します。スキーマがテストしているプロパティ名は常に文字列であることに注意してください。

このキーワードを省略した場合、空のスキーマと同じ動作になります。

10. 出力フォーマット

JSONスキーマはプラットフォームに依存しないように定義されています。そのため、プラットフォーム間での互換性を高めるために、実装は標準の検証出力フォーマットに準拠する必要があります。このセクションでは、コンシューマが検証結果を正しく解釈するために必要な最小限の要件について説明します。

10.1. フォーマット

JSONスキーマの出力は、9.2.1項で説明されているJSONスキーマデータインスタンスモデルを使用して定義されています。実装は、特定の言語やプラットフォームでサポートされているように、これと異なる場合がありますが、出力はここで定義されているJSON形式にシリアライゼーションまたはその他の手段によって変換可能であることが推奨されます。

10.2. 出力フォーマット

この仕様では、4つの出力フォーマットを定義しています。「出力構造」セクションで、各フォーマットの要件を参照してください。

実装は、少なくとも「フラグ」、「基本」、または「詳細」フォーマットを提供する必要があり、「冗長」フォーマットを提供してもかまいません。複雑なフォーマットの1つ以上を提供する場合は、「フラグ」フォーマットも提供する必要があります。実装は、サポートするフォーマットをドキュメントで指定する必要があります。

10.3. 最小限の情報

単純な「フラグ」出力以外にも、スキーマまたはインスタンスのデバッグに役立つ追加情報があります。各サブ結果は、少なくともこのセクションに含まれる情報を含む必要があります。

これらのコンポーネントをすべて含む単一のオブジェクトは、出力単位とみなされます。

実装では、追加情報を提供することを選択しても構いません。

10.3.1.キーワードの相対位置

検証パスに続く検証キーワードの相対位置。値はJSONポインタとして表現する必要があり、"$ref"や"$recursiveRef"などの参照による適用子を含める必要があります。

#/properties/width/$ref/minimum

                        

これらの参照による適用子キーワードが含まれているため、このポインタは通常のJSONポインタ処理では解決できない場合があります。

この情報のJSONキーは"keywordLocation"です。

10.3.2.キーワードの絶対位置

検証キーワードの絶対的な、参照解決済みの位置。値は、関連するスキーマオブジェクトの標準URIを使用する絶対URIとして表現する必要があり、非終端パスコンポーネントとして"$ref"や"$recursiveRef"などの参照による適用子を含めることはできません。エラーまたはアノテーションがそのキーワード(解決できない参照など)のものである場合、そのようなキーワードで終わっても構いません。

https://example.com/schemas/common#/$defs/count/minimum

                        

相対位置に参照が含まれていない場合、またはスキーマが"$id"として絶対URIを宣言していない場合にのみ、この情報を省略しても構いません。

この情報のJSONキーは"absoluteKeywordLocation"です。

10.3.3.インスタンスの位置

検証対象のインスタンス内のJSON値の位置。値はURIフラグメントエンコードされたJSONポインタとして表現する必要があります。

この情報のJSONキーは"instanceLocation"です。

10.3.4.エラーまたはアノテーション

検証によって生成されるエラーまたはアノテーション。

エラーの場合、メッセージの具体的な表現はこの仕様では定義されていません。実装ではこれを提供する必要があります。

アノテーションの場合、アノテーションを生成する各キーワードは、そのフォーマットを指定します。デフォルトでは、キーワードの値です。

検証に失敗した場合のJSONキーは"error"、検証に成功した場合のJSONキーは"annotation"です。

10.3.5.ネストされた結果

2つの階層構造について、このプロパティはネストされたエラーとアノテーションを保持します。

検証に失敗した場合のネストされた結果のJSONキーは"errors"、検証に成功した場合のJSONキーは"annotations"です。キーワードにネストされた結果がある場合、ローカルエラーまたはアノテーションを持つこともできるため、複数形を使用することに注意してください。

10.4.出力構造

出力は、"valid"という名前のブール値のプロパティを含むオブジェクトである必要があります。結果に関する追加情報が必要な場合、出力には以下のように"errors"または"annotations"も含まれている必要があります。

これらの例では、次のスキーマとインスタンスが使用されます。

{
  "$id": "https://example.com/polygon",
  "$schema": "https://json-schema.dokyumento.jp/draft/2019-09/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
  }
]

                    

このインスタンスは検証に失敗し、エラーを生成しますが、アノテーションを生成する合格するスキーマの例を推測することは簡単です。

具体的には、生成されるエラーは次のとおりです。

これらの例に示されているエラーメッセージの表現は、この仕様の要件ではありません。実装では、対象者向けに合わせたエラーメッセージを作成するか、ユーザーが独自のメッセージを作成できるテンプレートメカニズムを提供する必要があります。

10.4.1.フラグ

最も単純なケースでは、"valid"プロパティのブール値の結果を満たすだけで済みます。

{
  "valid": false
}

                        

この形式ではエラーまたはアノテーションが返されないため、実装では、結果を決定できるようになった時点ですぐに失敗または成功を返す短絡論理を使用することをお勧めします。たとえば、「anyOf」キーワードに5つのサブスキーマが含まれており、2番目のサブスキーマが合格した場合、他の3つのサブスキーマをチェックする必要はありません。論理は、単に成功で返すことができます。

10.4.2.基本

"基本"構造は、出力単位のフラットリストです。

{
  "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"
    }
  ]
}

                        

10.4.3.詳細

"詳細"構造はスキーマに基づいており、人間と機械の両方にとってより読みやすくなります。このように構造を整理することで、エラー間の関連付けがより明確になります。たとえば、「y」プロパティの欠落と「z」プロパティの追加の両方が、インスタンス内の同じ位置に由来するということは、「基本」構造ではすぐに明らかになりません。階層構造では、相関関係をより簡単に特定できます。

結果オブジェクトの構築を規定するルールを以下に示します。

ブランチノードには、エラーメッセージまたはアノテーションは必要ありません。

{
  "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"
    }
  ]
}

                        

10.4.4.冗長

"冗長"構造は、スキーマと完全に一致する完全に実現された階層です。この構造は、エラーの位置が重要なフォーム生成と検証に役立ちます。

"詳細"構造との主な違いは、すべての結果が返されることです。これには、それ以外の場合削除されるサブスキーマ検証結果(例:「not」キーワード内の検証に失敗したアノテーション、検証に成功したアノテーションなど)も含まれます。このため、各ノードにも`valid`プロパティを含めて、そのノードの検証結果を示すことをお勧めします。

この出力構造は非常に大きくなる可能性があるため、簡潔にするために小さな例を以下に示します。上記の例の完全な出力構造のURIは次のとおりです。<https://json-schema.dokyumento.jp/draft/2019-09/output/verbose-example>

// schema
{
  "$id": "https://example.com/polygon",
  "$schema": "https://json-schema.dokyumento.jp/draft/2019-09/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."
        }
      ]
    }
  ]
}

                        

10.4.5.出力検証スキーマ

便宜上、実装によって生成された出力を検証するためのJSONスキーマが提供されています。そのURIは次のとおりです。<https://json-schema.dokyumento.jp/draft/2019-09/output/schema>

11. ハイパーメディアの使用方法

JSONは、自動化されたAPIとロボットのためにHTTPサーバーで広く採用されています。このセクションでは、メディアタイプとWebリンクをサポートするプロトコルで使用する場合、よりRESTfulな方法でJSONドキュメントの処理を強化する方法について説明します。

11.1.スキーマへのリンク

リンクデータプロトコル1.0、セクション8.1で定義されているように、スキーマによって記述されたインスタンスは、ダウンロード可能なJSONスキーマへのリンクを「describedby」リンクリレーションを使用して提供することをお勧めします。

HTTPでは、そのようなリンクはLinkヘッダーを使用して任意のレスポンスに添付できます。そのようなヘッダーの例を以下に示します。

Link: <https://example.com/my-hyper-schema#>; rel="describedby"

                    

11.2. メディアタイプパラメーターによるスキーマの識別

メディアタイプでは、「schema」メディアタイプパラメーターを許可しても構いません。これにより、HTTPサーバーはスキーマに基づいてコンテンツタイプネゴシエーションを実行できます。メディアタイプパラメーターは、空白で区切られたURIのリストである必要があります(つまり、相対参照は無効です)。

メディアタイプapplication/schema-instance+jsonを使用する場合は、「schema」パラメーターを指定する必要があります。

メディアタイプapplication/schema+jsonを使用する場合は、「schema」パラメーターを指定しても構いません。指定する場合は、"$schema"キーワードによって識別されたURIと同じURIを含める必要があり、追加のURIを含めることもできます。メディアタイプパラメーターとして代替または追加のメタスキーマが存在する場合でも、「$schema」URIはスキーマの標準メタスキーマと見なす必要があります。

スキーマURIは不透明であり、自動的に参照解決してはなりません。実装が提供されたスキーマのセマンティクスを理解していない場合、実装は代わりに「describedby」リンク(存在する場合)に従うことができます。これにより、スキーマの処理方法に関する情報が提供される場合があります。「schema」は必ずしもネットワーク上の場所を指しているわけではないため、「describedby」リレーションはダウンロード可能なスキーマへのリンクに使用されます。ただし、簡潔にするために、スキーマの作成者は、可能であればこれらのURIを同じリソースにポイントするようにする必要があります。

HTTPでは、メディアタイプパラメーターはContent-Typeヘッダー内に送信されます。

Content-Type: application/json;
          schema="https://example.com/my-hyper-schema#"

                    

複数のスキーマは空白で区切られ、インスタンスがリストされたすべてのスキーマに準拠していることを示します。

Content-Type: application/json;
          schema="https://example.com/alice https://example.com/bob"

                    

メディアタイプパラメーターは、HTTPのAcceptリクエストヘッダーでも使用されます。

Accept: application/json;
          schema="https://example.com/qiang https://example.com/li",
        application/json;
          schema="https://example.com/kumar"

                    

Content-Typeと同様に、同じ文字列内の複数のスキーマパラメーターは、リストされたすべてのスキーマに準拠するインスタンスを要求します。

Content-Typeとは異なり、Acceptは、クライアントが複数のメディアタイプを受け入れることができることを示すために複数の値を含めることができます。上記の例では、2つのメディアタイプはスキーマパラメーターの値のみが異なることに注意してください。これは、識別されたスキーマの少なくとも1つに準拠するapplication/json表現を要求します。

[CREF14]この段落では、「schema」リンクリレーションを登録できると仮定しています。「tag:json-schema.org,2017:schema」のようなものを代わりに指定する必要がありますか? HTTPはLinkで「schema」を送信することもできますが、これがメディアタイプパラメーターを完全に置き換える場合、メディアタイプのセマンティクスとContent-Typeネゴシエーションに影響を与える可能性があります。

Link: </alice>;rel="schema", </bob>;rel="schema"

                    

11.3.HTTP経由での使用

ネットワーク上のハイパーメディアシステムで使用する場合、HTTPはスキーマを配布するためのプロトコルとして頻繁に使用されます。動作の悪いクライアントは、代わりにスキーマを長期間キャッシュできる場合に、ネットワーク経由でスキーマを必要以上に頻繁にプルする場合、サーバー管理者にとって問題となる可能性があります。

HTTPサーバーは、JSONスキーマで長寿命のキャッシュヘッダーを設定する必要があります。HTTPクライアントはキャッシュヘッダーを遵守し、その有効期限内にドキュメントを再要求してはなりません。分散システムは、共有キャッシュやキャッシングプロキシを使用する必要があります。

User-Agent: product-name/5.4.1 so-cool-json-schema/1.0.2 curl/7.43.0

                        

クライアントは、JSONスキーマの実装またはソフトウェア製品に固有のUser-Agentヘッダーを設定または追加する必要があります。記号は重要度の高い順にリストされているため、JSONスキーマライブラリの名前/バージョンは、より一般的なHTTPライブラリの名前(存在する場合)の前に置く必要があります。例を以下に示します。

クライアントは、「From」ヘッダー付きのリクエストを行うことができる必要があるため、サーバーオペレーターは動作の悪いスクリプトの所有者に連絡できます。

12. セキュリティに関する考慮事項

スキーマとインスタンスの両方がJSON値です。そのため、RFC 8259で定義されているすべてのセキュリティに関する考慮事項が適用されます。

インスタンスとスキーマの両方が、多くの場合、信頼できない第三者によって記述され、パブリックインターネットサーバーに配置されます。検証者は、スキーマに対する解析と検証によって過剰なシステムリソースが消費されないように注意する必要があります。検証者は、無限ループに陥ってはなりません。

サーバーは、悪意のある当事者が、既存の"$id"を持つスキーマをアップロードすることによって、既存のスキーマの機能を変更できないようにする必要があります。

個々のJSONスキーマボキャブラリにも、独自のセキュリティに関する考慮事項がある可能性があります。詳細については、それぞれの仕様を参照してください。

スキーマの作成者は、「$comment」の内容に注意する必要があります。悪意のある実装では、仕様に違反してエンドユーザーに表示したり、そのような動作が期待されている場合に削除できなかったりする場合があります。

悪意のあるスキーマの作成者は、「$comment」内に実行可能コードやその他の危険な資料を配置する可能性があります。実装では、「$comment」の内容に基づいて解析したり、アクションを実行したりしてはなりません。

13.IANAに関する考慮事項

13.1. application/schema+json

JSONスキーマの提案されたMIMEメディアタイプは、次のように定義されています。

13.2. application/schema-instance+json

JSONスキーマ固有のメディアタイプを必要とするJSONスキーマインスタンスの提案されたMIMEメディアタイプは、次のように定義されます。

14. 参考文献

14.1. 標準参照

[ecma262] "ECMA 262仕様"
[RFC2119] Bradner, S.、"RFCにおける要件レベルを示すためのキーワード"、BCP 14、RFC 2119、DOI 10.17487/RFC2119、1997年3月。
[RFC3986] Berners-Lee, T.Fielding, R.、およびL. Masinter、"Uniform Resource Identifier (URI): Generic Syntax"、STD 66、RFC 3986、DOI 10.17487/RFC3986、2005年1月。
[RFC6839] Hansen, T.およびA. Melnikov、"追加メディアタイプ構造化構文サフィックス"、RFC 6839、DOI 10.17487/RFC6839、2013年1月。
[RFC6901] Bryan, P.Zyp, K.、およびM. Nottingham、"JavaScript Object Notation (JSON) Pointer"、RFC 6901、DOI 10.17487/RFC6901、2013年4月。
[RFC8259] Bray, T.、"The JavaScript Object Notation (JSON) Data Interchange Format"、STD 90、RFC 8259、DOI 10.17487/RFC8259、2017年12月。
[W3C.REC-ldp-20150226] Speicher, S.Arwe, J.、およびA. Malhotra、"Linked Data Platform 1.0"、World Wide Web Consortium Recommendation REC-ldp-20150226、2015年2月。

14.2. 参考参照

[json-hyper-schema] Andrews, H.およびA. Wright、"JSON Hyper-Schema: A Vocabulary for Hypermedia Annotation of JSON"、Internet-Draft draft-handrews-json-schema-hyperschema-02、2017年11月。
[json-schema-validation] Wright, A.Andrews, H.、およびG. Luff、"JSON Schema Validation: A Vocabulary for Structural Validation of JSON"、Internet-Draft draft-handrews-json-schema-validation-02、2017年11月。
[RFC6596] Ohye, M.およびJ. Kupke、"The Canonical Link Relation"、RFC 6596、DOI 10.17487/RFC6596、2012年4月。
[RFC7049] Bormann, C.およびP. Hoffman、"Concise Binary Object Representation (CBOR)"、RFC 7049、DOI 10.17487/RFC7049、2013年10月。
[RFC7231] Fielding, R.およびJ. Reschke、"Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content"、RFC 7231、DOI 10.17487/RFC7231、2014年6月。
[RFC8288] Nottingham, M.、"Web Linking"、RFC 8288、DOI 10.17487/RFC8288、2017年10月。
[W3C.WD-fragid-best-practices-20121025] Tennison, J.、"Best Practices for Fragment Identifiers and Media Type Definitions"、World Wide Web Consortium WD WD-fragid-best-practices-20121025、2012年10月。

付録A. スキーマ識別例

ルートスキーマと様々なサブスキーマの両方を識別するために"$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ポインタ(ルートスキーマを基準とする)にあるスキーマは、以下のベースURIを持ち、上記のセクション5および8.2.2.2に従って、リストされている任意のURIによって識別可能です。

# (ドキュメントルート)
標準的な絶対URI(およびベースURI)
https://example.com/root.json
ポインタフラグメントを含む標準的なURI
https://example.com/root.json#

#/$defs/A
ベースURI
https://example.com/root.json
プレーンなフラグメントを含む標準的なURI
https://example.com/root.json#foo
ポインタフラグメントを含む標準的なURI
https://example.com/root.json#/$defs/A

#/$defs/B
ベースURI
https://example.com/other.json
ポインタフラグメントを含む標準的なURI
https://example.com/other.json#
root.jsonを基準としたフラグメントを含む非標準的なURI
https://example.com/root.json#/$defs/B

#/$defs/B/$defs/X
ベースURI
https://example.com/other.json
プレーンなフラグメントを含む標準的なURI
https://example.com/other.json#bar
ポインタフラグメントを含む標準的なURI
https://example.com/other.json#/$defs/X
root.jsonを基準としたフラグメントを含む非標準的なURI
https://example.com/root.json#/$defs/B/$defs/X

#/$defs/B/$defs/Y
ベースURI
https://example.com/t/inner.json
プレーンなフラグメントを含む標準的なURI
https://example.com/t/inner.json#bar
ポインタフラグメントを含む標準的なURI
https://example.com/t/inner.json#
other.jsonを基準としたフラグメントを含む非標準的なURI
https://example.com/other.json#/$defs/Y
root.jsonを基準としたフラグメントを含む非標準的なURI
https://example.com/root.json#/$defs/B/$defs/Y

#/$defs/C
ベースURI
urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f
ポインタフラグメントを含む標準的なURI
urn:uuid:ee564b8a-7a87-4125-8c96-e9f123d6766f#
root.jsonを基準としたフラグメントを含む非標準的なURI
https://example.com/root.json#/$defs/C

付録B. スキーマドキュメントと参照の操作

参照("$ref")がどのようにそしてどこに現れるかに基づいて、スキーマドキュメントを再配置するために、様々なツールが作成されてきました。この付録では、この仕様に準拠するユースケースとアクションについて説明します。

B.1. スキーマリソースを単一ドキュメントにバンドルする

一緒に使用する予定のスキーマリソースのセットは、それぞれが独自のスキーマドキュメントにあるように整理したり、すべてを同じスキーマドキュメントに含めたり、その間の任意の粒度のドキュメントグループ化を行うことができます。

様々な種類の参照削除を実行するための多くのツールが存在します。一般的なケースとしては、すべての参照をそのファイル内で解決できる単一ファイルを作成することが挙げられます。これは、通常、配布を簡素化するため、またはJSONスキーマライブラリの様々な呼び出しが多数のリソースの追跡とロードを続ける必要がないようにコーディングを簡素化するために実行されます。

すべての静的参照(例:"$ref")が標準的なURIに解決されるURI参照を使用し、すべてのスキーマリソースがルートスキーマに絶対URIを"$id"として持つ限り、この変換は安全かつ可逆的に実行できます。

これらの条件を満たすと、各外部リソースを"$defs"の下にコピーできます。リソースのスキーマオブジェクト間の参照を壊すことなく、検証またはアノテーションの結果のあらゆる側面を変更することなくコピーできます。埋め込まれたリソースの標準的なURIには表示されないため、"$defs"の下のスキーマの名前は、それぞれがユニークであると仮定すると、動作に影響しません。

B.2. 参照の削除は常に安全とは限らない

すべての参照を削除して単一のスキーマドキュメントを作成しようとすると、必ずしも元の形式と同じ動作を持つスキーマが生成されるとは限りません。

"$ref"は現在、他のキーワードと同じスキーマオブジェクトに許可される他のキーワードと同様に扱われるため、すべてのケースで非再帰的な"$ref"削除を完全にサポートするには、比較的複雑なスキーマ操作が必要になる場合があります。スキーマ構造だけでなく、意図された用途にも依存するため、安全な"$ref"削除変換のセットを決定または提供することは、この仕様の範囲外です。

付録C. 再帰的なスキーマ拡張の例

ツリー内の各ノードが任意の種類の"data"フィールドを持つことができる単純な再帰的なツリー構造を記述する次の2つのスキーマを考えてみましょう。最初のスキーマは他のインスタンスプロパティを許可し無視します。2番目はより厳格で、"data"と"children"プロパティのみを許可します。"data"が"daat"と誤って表記されたインスタンスの例も示されています。

// tree schema, extensible
{
    "$schema": "https://json-schema.dokyumento.jp/draft/2019-09/schema",
    "$id": "https://example.com/tree",
    "$recursiveAnchor": true,

    "type": "object",
    "properties": {
        "data": true,
        "children": {
            "type": "array",
            "items": {
                "$recursiveRef": "#"
            }
        }
    }
}

// strict-tree schema, guards against misspelled properties
{
    "$schema": "https://json-schema.dokyumento.jp/draft/2019-09/schema",
    "$id": "https://example.com/strict-tree",
    "$recursiveAnchor": true,

    "$ref": "tree",
    "unevaluatedProperties": false
}

// instance with misspelled field
{
    "children": [ { "daat": 1 } ]
}

                

インスタンスに"strict-tree"スキーマを適用すると、"$ref"を"tree"スキーマに追跡し、その"children"サブスキーマを調べ、その"items"サブスキーマで"$recursiveAnchor"を見つけます。この時点で、動的パスは"#/$ref/properties/children/items/$recursiveRef"です。

この時点でのベースURIは"https://example.com/tree"であるため、"$recursiveRef"は最初は"https://example.com/tree#"に解決されます。"recursiveAnchor"がtrueであるため、動的パスを調べて使用する異なるベースURIがあるかどうかを確認します。"#"と"#/$ref"の動的パスでtrueの値を持つ"$recursiveAnchor"を見つけます。

最も外側のものは"#"であり、これは"strict-tree"スキーマのルートスキーマであるため、そのベースURIである"https://example.com/strict-tree"を使用します。これにより、"$recursiveRef"の最終的な解決済みURIとして"https://example.com/strict-tree#"が生成されます。

このようにして、"tree"スキーマの再帰は"strict-tree"のルートに再帰し、インスタンスルートに"strict-tree"を適用するだけでなく、インスタンスの子に"tree"を適用します。

付録D. ボキャブラリの使用

D.1. ボキャブラリとメタスキーマの作成者のベストプラクティス

ボキャブラリ作成者は、ボキャブラリが広範に使用され、他のボキャブラリと組み合わされる可能性がある場合、キーワード名の衝突を避けるように注意する必要があります。JSONスキーマは正式な名前空間システムを提供しませんが、キーワード名を制限することもなく、任意の数の名前空間アプローチを許可します。

ボキャブラリは互いに構築できます。たとえば、他のボキャブラリのキーワードの動作に関してキーワードの動作を定義したり、許容される値の制限されたセットまたは拡張されたセットを使用して他のボキャブラリのキーワードを使用したりすることによって構築できます。このようなボキャブラリの再利用すべてが、それが構築されているボキャブラリと互換性のある新しいボキャブラリになるわけではありません。ボキャブラリ作成者は、互換性のレベル(もしあれば)を明確に文書化する必要があります。

メタスキーマ作成者は、同じキーワードに対して相反する構文またはセマンティクスを定義する複数のボキャブラリを組み合わせるために"$vocabulary"を使用しないでください。セマンティックな競合は一般的にスキーマ検証では検出できないため、実装ではそのような競合を検出することは想定されていません。競合するボキャブラリが宣言されている場合、結果の動作は未定義です。

ボキャブラリ作成者は、ボキャブラリのキーワードの期待される使用方法を独自に検証するメタスキーマを提供する必要があります。そのようなメタスキーマは追加のキーワードを禁止するべきではなく、コアボキャブラリのキーワードを禁止するべきではありません。

メタスキーマ作成者は、"allOf"キーワードを使用して各ボキャブラリのメタスキーマを参照することをお勧めしますが、特定のユースケースでは、メタスキーマを作成するための他のメカニズムが適切な場合があります。

メタスキーマの再帰的な性質により、"$recursiveAnchor"と"$recursiveRef"キーワードは、既存のメタスキーマを拡張するために特に役立ちます。これは、検証メタスキーマを拡張するJSONハイパー・スキーマ・メタスキーマで見ることができます。

メタスキーマは、宣言されたボキャブラリに関連付けられたメタスキーマが記述しているもの以上に、追加の制約を課すことができます。これには、任意のボキャブラリに存在しないキーワードの説明が含まれます。これは、ボキャブラリのサブセットへの使用を制限し、再利用を意図していないローカルに定義されたキーワードを検証するために使用できます。

ただし、メタスキーマは、ボキャブラリが期待するものとは異なるJSONタイプを要求することなどによって、宣言するボキャブラリと矛盾するべきではありません。結果の動作は未定義です。

任意の実装でボキャブラリのサポートをテストする必要がないローカル使用を目的としたメタスキーマは、"$vocabulary"を完全に省略できます。

D.2. ボキャブラリ宣言を含むメタスキーマの例

このメタスキーマは、コアボキャブラリとアプリケーションボキャブラリの両方と、拡張ボキャブラリを明示的に宣言し、「allOf」でそれらのメタスキーマを組み合わせます。主要なメタスキーマの例の後には、そのボキャブラリのキーワードのみを記述する拡張ボキャブラリのメタスキーマが表示されます。

主要な例となるメタスキーマは、実装が特に複雑な "unevaluated" で始まるキーワードを禁止することにより、Applicatorボキャブラリの使用を制限しています。これは、Applicatorボキャブラリによって定義されたセマンティクスやキーワードの集合を変えるものではありません。「unevaluted」で始まるキーワードを使用しようとする、このメタスキーマを使用するスキーマの検証がこのメタスキーマに対して失敗することを保証するだけです。

最後に、このメタスキーマは、どのボキャブラリにも属さないキーワード "localKeyword" の構文を記述しています。このメタスキーマの実装者とユーザーは、"localKeyword" のセマンティクスを理解するものと想定されます。JSON Schemaは、ボキャブラリの外部でキーワードのセマンティクスを表現するメカニズムを定義していないため、それらが理解されている特定の環境を除いて、使用するには適していません。

このメタスキーマは、一般的に使用されるいくつかのボキャブラリを組み合わせています。

{
  "$schema": "https://json-schema.dokyumento.jp/draft/2019-09/schema",
  "$id": "https://example.com/meta/general-use-example",
  "$recursiveAnchor": true,
  "$vocabulary": {
    "https://json-schema.dokyumento.jp/draft/2019-09/vocab/core": true,
    "https://json-schema.dokyumento.jp/draft/2019-09/vocab/applicator": true,
    "https://json-schema.dokyumento.jp/draft/2019-09/vocab/validation": true,
    "https://example.com/vocab/example-vocab": true
  },
  "allOf": [
    {"$ref": "https://json-schema.dokyumento.jp/draft/2019-09/meta/core"},
    {"$ref": "https://json-schema.dokyumento.jp/draft/2019-09/meta/applicator"},
    {"$ref": "https://json-schema.dokyumento.jp/draft/2019-09/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.dokyumento.jp/draft/2019-09/schema",
  "$id": "https://example.com/meta/example-vocab",
  "$recursiveAnchor": true,
  "$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" で参照される各単一ボキャブラリメタスキーマは対応するボキャブラリを宣言していますが、この新しいメタスキーマはそれらを再宣言する必要があります。

コアとバリデーション仕様によって定義されたすべてのボキャブラリを組み合わせた標準的なメタスキーマ、そしてそれらの仕様とハイパー-スキーマ仕様によって定義されたすべてのボキャブラリを組み合わせたメタスキーマは、追加の複雑な組み合わせを示しています。これらのメタスキーマのURIは、それぞれバリデーション仕様とハイパー-スキーマ仕様で見つけることができます。

汎用メタスキーマは "minDate" の構文を検証できますが、"minDate" のセマンティックな意味の背後にあるロジックを定義するのはボキャブラリです。「minDate」のセマンティクス(この例では、インスタンスの値は、スキーマ内のキーワードの値として提供された日付以降の日付でなければならない)を理解せずに、実装は構文の使用のみを検証できます。この場合、それは日付形式の文字列であることを検証することを意味します(バリデーション仕様で説明されているように、「format」関数が純粋にアノテーションとして機能する場合でも、「pattern」を使用して検証されるようにします)。

付録E. 参考文献と生成的なユースケース

参照の存在は検証結果に対して透過的であることが期待されますが、コードジェネレーターや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" の最初の参照は、基底クラスとして示されています。2番目はクラスの関係が割り当てられていないため、コードジェネレーターは参照がないかのようにターゲットの定義をこれと組み合わせる必要があります。

プロパティを見ると、「foo」はオブジェクト合成としてフラグ付けされていますが、「date」プロパティはフラグ付けされていません。それは単にサブフィールドを持つフィールドであり、別個のクラスのインスタンスではありません。

この使用方法では、アノテーションは参照と同じオブジェクトに存在する必要があり、参照として認識可能である必要があります。

付録F. 謝辞

JSON Schemaの初期ドラフト作成にご尽力いただいたGary Court、Francis Galiegue、Kris Zyp、Geraint Luffの皆様に感謝いたします。

このドキュメントへの提出とパッチにご尽力いただいたJason Desrosiers、Daniel Perrett、Erik Wilde、Ben Hutton、Evgeny Poberezkin、Brad Bowman、Gowry Sankar、Donald Pipowitch、Dave Finlayの皆様に感謝いたします。

付録G. 変更ログ

[CREF15]インターネットドラフトのステータスを離れる前にこのセクションを削除してください。

draft-handrews-json-schema-02

draft-handrews-json-schema-01

draft-handrews-json-schema-00

draft-wright-json-schema-01

draft-wright-json-schema-00

draft-zyp-json-schema-04

draft-zyp-json-schema-00

著者アドレス

オースティン・ライト(編集者) メール:[メールアドレス保護]
ヘンリー・アンドリュース(編集者) メール:[メールアドレス保護]
ベン・ハットン(編集者) ウェルカムサンガー研究所 メール:[メールアドレス保護] URI:https://jsonschema.dev
グレッグ・デニス オークランド ニュージーランド メール:[メールアドレス保護]