インターネット技術特別調査委員会 | A. ライト (編) |
インターネットドラフト | |
目的ステータス:情報提供 | H. アンドリュース (編) |
有効期限:2021年8月1日 | |
B. ハットン (編) | |
G. デニス | |
2020年1月28日 |
JSONスキーマ:JSONドキュメントを記述するためのメディアタイプ
draft-bhutton-json-schema-00
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.dokyumento.jp/>を参照してください。
フィードバックを提供するには、この課題追跡ツール、ホームページに記載されているコミュニケーション方法を使用するか、ドキュメント編集者にメールで送信してください。
このインターネットドラフトは、BCP 78およびBCP 79の規定に完全に準拠して提出されています。
インターネットドラフトは、インターネット技術特別調査委員会(IETF)の作業ドキュメントです。他のグループもインターネットドラフトとして作業ドキュメントを配布する場合があることに注意してください。現在のインターネットドラフトのリストは、https://datatracker.ietf.org/drafts/current/ にあります。
インターネットドラフトは、最大6か月間有効なドラフトドキュメントであり、いつでも更新、置き換え、または他のドキュメントによって廃止される可能性があります。インターネットドラフトを参照資料として使用したり、「作業中」以外で引用したりすることは適切ではありません。
このインターネットドラフトは、2021年8月1日に失効します。
Copyright(c)2020 IETF Trustおよびドキュメント作成者として特定された人物。無断複写・転載を禁じます。
このドキュメントは、BCP 78およびこのドキュメントの発行日に有効なIETFトラストのIETFドキュメントに関する法的規定(https://trustee.ietf.org/license-info)に従うものとします。このドキュメントに関するあなたの権利と制限について説明しているため、これらのドキュメントを注意深く確認してください。このドキュメントから抽出されたコードコンポーネントには、トラスト法的規定のセクション4.eに記載されている簡略化BSDライセンステキストを含める必要があり、簡略化BSDライセンスに記載されているように保証なしで提供されます。
JSONスキーマは、JSONデータの構造を定義するためのJSONメディアタイプです。JSONスキーマは、JSONデータの検証、ドキュメント化、ハイパーリンクナビゲーション、およびインタラクション制御を定義することを目的としています。
この仕様は、JSONスキーマのコア用語とメカニズムを定義します。これには、参照による別のJSONスキーマのポイント、JSONスキーマ参照の逆参照、使用されている方言の指定、方言の語彙要件の指定、および期待される出力の定義が含まれます。
他の仕様は、検証、リンク、アノテーション、ナビゲーション、およびインタラクションに関するアサーションを実行する語彙を定義します。
このドキュメントにおけるキーワード "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", および "OPTIONAL" は、RFC 2119 に記載されているように解釈されます。
このドキュメントにおける「JSON」、「JSONテキスト」、「JSON値」、「メンバー」、「要素」、「オブジェクト」、「配列」、「数値」、「文字列」、「ブール値」、「true」、「false」、および「null」という用語は、RFC 8259 で定義されているように解釈されます。
このドキュメントでは、JSONデータを記述するためのJSONスキーマを識別するための新しいメディアタイプ「application/schema+json」を提案します。また、追加の統合機能を提供するために、さらにオプションのメディアタイプ「application/schema-instance+json」を提案します。JSONスキーマ自体はJSONドキュメントです。この仕様および関連する仕様では、作成者がJSONデータをいくつかの方法で記述できるようにするキーワードを定義します。
JSONスキーマは、キーワードを使用してJSONインスタンスに対する制約を表明したり、追加情報でそれらのインスタンスに注釈を付けたりします。追加のキーワードは、より複雑なJSONデータ構造にアサーションとアノテーションを適用したり、何らかの条件に基づいてアサーションとアノテーションを適用したりするために使用されます。
再利用を促進するために、キーワードは語彙に編成できます。語彙は、キーワードのリストと、その構文とセマンティクスで構成されます。ダイアレクトは、メタスキーマで識別される、語彙のセットとその必要なサポートとして定義されます。
JSON Schemaは、追加の語彙を定義するか、より形式にとらわれずに語彙外で追加のキーワードを定義することによって拡張できます。認識されない個々のキーワードは、その値が単にアノテーションとして収集されますが、認識されない語彙に関する動作は、どの語彙が使用中であるかを宣言するときに制御できます。
このドキュメントでは、すべての実装でサポートする必要があり、無効にすることができないコア語彙を定義します。そのキーワードには、必須の性質を強調するために「$」文字が先頭に付いています。この語彙は、「application/schema+json」メディアタイプの機能に不可欠であり、他の語彙のロードをブートストラップするために使用されます。
さらに、このドキュメントでは、サブスキーマを条件付きで適用するためのキーワードと、オブジェクトと配列の内容にサブスキーマを適用するための推奨語彙を定義します。この語彙またはそれに非常に似た語彙のいずれかは、アサーション検証、アノテーション、またはその両方を目的とするかにかかわらず、非自明なJSONインスタンスのスキーマを作成するために必要です。必須のコア語彙の一部ではありませんが、最大限の相互運用性のために、この追加の語彙はこのドキュメントに含まれており、その使用が強く推奨されています。
構造検証やハイパーメディアアノテーションなどの目的のための追加の語彙は、他のドキュメントで定義されています。これらの他のドキュメントではそれぞれ、そのドキュメントの目的のためにスキーマを作成するために必要な標準の語彙セットを収集したダイアレクトを定義しています。
JSONドキュメントは、application/jsonメディアタイプで記述された情報リソース(オクテットの系列)です。
JSON Schemaでは、定義するデータモデルのため、「JSONドキュメント」、「JSONテキスト」、「JSON値」という用語は交換可能です。
JSON Schemaは、JSONドキュメントのみで定義されます。ただし、CBORのようなメディアタイプを含め、JSON Schemaデータモデルに従って解析または処理できるドキュメントまたはメモリ構造は、JSON Schemaに対して解釈できます。
スキーマが適用されるJSONドキュメントは「インスタンス」と呼ばれます。
JSON Schemaは、「application/json」または「+json」という構造化構文サフィックスを持つメディアタイプを含む、互換性のあるドキュメントで定義されます。
これらの中で、この仕様は、URIのフラグメントの処理を定義する「application/schema-instance+json」メディアタイプを定義します。
JSON Schemaは、データモデルに従ってドキュメントを解釈します。このデータモデルに従って解釈されるJSON値を「インスタンス」と呼びます。
インスタンスには、6つのプリミティブタイプのいずれかと、タイプに応じて可能な値の範囲があります。
データモデル内で等しい数値の異なる語彙表現を含む、空白と書式設定に関する懸念は、JSON Schemaの範囲外です。JSON Schemaの語彙は、元のJSON表現のUnicode文字を使用するのではなく、データモデル内の書式付き文字列を正確に解釈するためのキーワードを定義する必要があります。
オブジェクトは同じキーを持つ2つのプロパティを持つことができないため、単一のオブジェクトで同じキーを持つ2つのプロパティを定義しようとするJSONドキュメントの動作は未定義です。
JSON Schemaの語彙は、独自の拡張型システムを自由に定義できることに注意してください。これは、ここで定義されているコアデータモデルの型と混同しないでください。例として、「integer」は、語彙がキーワードの値として定義するのに妥当な型ですが、データモデルは整数と他の数値とを区別しません。
2つのJSONインスタンスは、同じ型であり、データモデルに従って同じ値を持っている場合にのみ等しいと言われます。具体的には、これは次のことを意味します。
この定義には、配列は同じ長さでなければならず、オブジェクトは同じ数のメンバーを持たなければならず、オブジェクトのプロパティは順不同であり、同じキーを持つ複数のプロパティを定義する方法はなく、単なる書式設定の違い(インデント、コンマの配置、末尾のゼロ)は重要ではないことが含まれています。
インスタンスが6つのJSONデータ型のいずれかの外にある可能性がある、JSON SchemaデータモデルのスーパーセットでJSON Schemaを使用することが可能です。
この場合、アノテーションは引き続き適用されます。ただし、ほとんどの検証キーワードは、常に成功するか、常に失敗するため、役立ちません。
カスタム語彙は、コアデータモデルのスーパーセットのサポートを定義できます。スキーマ自体は、このスーパーセットでのみ表現できる場合があります。たとえば、「const」キーワードを使用するためです。
JSON Schemaドキュメント、または単にスキーマは、インスタンスを記述するために使用されるJSONドキュメントです。スキーマ自体はインスタンスとして解釈できますが、「application/schema-instance+json」ではなく、「application/schema+json」メディアタイプを常に指定する必要があります。「application/schema+json」メディアタイプは、「application/schema-instance+json」によって提供されるフラグメント識別子構文とセマンティクスのスーパーセットを提供するために定義されています。
JSON Schemaは、オブジェクトまたはブール値でなければなりません。
インスタンスに適用されるオブジェクトのプロパティは、キーワードまたはスキーマキーワードと呼ばれます。大まかに言うと、キーワードは5つのカテゴリのいずれかに分類されます。
キーワードは複数のカテゴリに分類される場合がありますが、アプリケーターはサブスキーマの結果に基づいてアサーション結果のみを生成する必要があります。サブスキーマとは独立した追加の制約を定義しないでください。
同じスキーマオブジェクト内のプロパティであるキーワードは、隣接キーワードと呼ばれます。
このドキュメントとその関連ドキュメントの外で定義された拡張キーワードは、他の動作も自由に定義できます。
JSON Schemaには、スキーマキーワードではないプロパティを含めることができます。不明なキーワードは、キーワードの値がアノテーションの値であるアノテーションとして扱う必要があります。
空のスキーマは、プロパティがないか、不明なプロパティのみを持つJSON Schemaです。
ブール値のスキーマ値「true」と「false」は、インスタンス値に関係なく、常に自身をアサーション結果として生成する自明なスキーマです。アノテーション結果は生成されません。
これらのブール値スキーマは、スキーマ作成者の意図を明確にし、スキーマ処理の最適化を促進するために存在します。これらは、次のスキーマオブジェクト(「not」はこのドキュメントで定義されているサブスキーマアプリケーション語彙の一部です)と同一に動作します。
空のスキーマオブジェクトはあいまいではありませんが、「false」スキーマには多くの同等のものが考えられます。ブール値を使用すると、意図が人間と実装の両方に明確になります。
スキーマ語彙、または単に語彙は、キーワード、その構文、およびセマンティクスのセットです。語彙は、一般的に特定の目的を中心に編成されています。検証、ハイパーメディア、ユーザーインターフェイスの生成など、JSON Schemaのさまざまな使用法には、異なる語彙セットが含まれます。
語彙は、スキーマの作成者がスキーマを処理するためにどの語彙が必要かまたはオプションかを指示できるため、JSON Schemaの再利用の主要な単位です。語彙はメタスキーマ内のURIによって識別されるため、一般的な実装は、以前に不明な語彙をサポートするための拡張機能をロードできます。キーワードは語彙の外でサポートできますが、個々のキーワードの使用を示す同様のメカニズムはありません。
スキーマ自体を記述するスキーマは、メタスキーマと呼ばれます。メタスキーマは、JSON Schemaを検証し、どの語彙を使用しているかを指定するために使用されます。
通常、メタスキーマは語彙のセットを指定し、それらの語彙の構文に準拠するスキーマを検証します。ただし、メタスキーマが語彙の仕様が要求するよりも厳密または緩やかにスキーマ適合性を検証できるようにするために、メタスキーマと語彙は分離されています。メタスキーマは、正式な語彙の一部ではない追加のキーワードを記述および検証することもできます。
JSON Schemaリソースは、正規の絶対URIによって識別されるスキーマです。
ルートスキーマとは、問題となっているJSONドキュメント全体を構成するスキーマのことです。ルートスキーマは常にスキーマのリソースであり、そのURIは9.1.1節で説明されているように決定されます。
一部のキーワードはスキーマ自体を受け取るため、JSONスキーマをネストさせることができます。
{ "title": "root", "items": { "title": "array item" } }
このドキュメント例では、「配列項目」というタイトルのスキーマはサブスキーマであり、「ルート」というタイトルのスキーマはルートスキーマです。
ルートスキーマと同様に、サブスキーマもオブジェクトまたはブール値のいずれかです。
8.2.1節で説明したように、JSONスキーマドキュメントには複数のJSONスキーマリソースを含めることができます。無条件に使用される場合、「ルートスキーマ」という用語はドキュメントのルートスキーマを指します。場合によっては、リソースルートスキーマが議論されることがあります。リソースのルートスキーマは、そのトップレベルのスキーマオブジェクトであり、そのリソースがスタンドアロンのJSONスキーマドキュメントに抽出された場合にも、ドキュメントのルートスキーマとなります。
複数のスキーマリソースが埋め込まれているか、参照でリンクされているかに関わらず、それらは同じ方法で、同じ利用可能な動作で処理されます。
RFC 6839の3.1項に従い、任意の+jsonメディアタイプに指定されたフラグメント識別子の構文と意味は、「application/json」で指定されたものと同じであるべきです。(このドキュメントの発行時点では、「application/json」に定義されたフラグメント識別子の構文はありません。)
さらに、「application/schema+json」メディアタイプは、プレーン名とJSONポインタの2つのフラグメント識別子構造をサポートしています。「application/schema-instance+json」メディアタイプは、JSONポインタの1つのフラグメント識別子構造をサポートしています。
URIフラグメント識別子としてのJSONポインタの使用は、RFC 6901で説明されています。2つのフラグメント識別子構文をサポートする「application/schema+json」の場合、空の文字列を含むJSONポインタ構文に一致するフラグメント識別子は、JSONポインタフラグメント識別子として解釈する必要があります。
W3Cのフラグメント識別子のベストプラクティスに従い、「application/schema+json」のプレーン名フラグメント識別子は、ローカルで名前が付けられたスキーマを参照するために予約されています。JSONポインタ構文に一致しないすべてのフラグメント識別子は、プレーン名フラグメント識別子として解釈する必要があります。
「application/schema+json」ドキュメント内のプレーン名フラグメント識別子の定義と参照は、"$anchor"キーワードのセクションで指定されています。
インスタンスは、JSONで定義されている有効なJSON値であれば何でも構いません。JSONスキーマは型に関する制限を課しません。JSONスキーマは、例えばnullを含む任意のJSON値を記述できます。
JSONスキーマはプログラミング言語に依存せず、データモデルで記述されたすべての範囲の値をサポートします。ただし、一部の言語とJSONパーサーは、JSONで記述可能なすべての範囲の値をメモリ内で表現できない可能性があることに注意してください。
一部のプログラミング言語およびパーサーでは、浮動小数点数と整数に対して異なる内部表現を使用します。
一貫性を保つために、整数のJSON数値は小数部でエンコードするべきではありません。
キーワードは、制約を表現したり、インスタンス値を正規表現に制限したりするために正規表現を使用してもよいです。これらの正規表現は、ECMA-262、21.2.1節で説明されている正規表現の方言に従って有効であるべきです。
正規表現は、Unicodeサポートを提供するために「u」フラグ(または同等のもの)を使用して構築するか、ECMA-262で定義されているようにUnicodeサポートを提供するような方法で処理する必要があります。
さらに、正規表現の構造のサポートには大きなばらつきがあるため、スキーマの作成者は、以下の正規表現トークンに限定する必要があります。
最後に、実装は正規表現を、先頭にも末尾にもアンカーされているとみなしてはいけません。これは、例えば、パターン「es」が「expression」に一致することを意味します。
追加のスキーマキーワードおよびスキーマ語彙は、任意のエンティティによって定義できます。明示的な合意がない限り、スキーマの作成者は、そのようなサポートを明示的に文書化していない実装によって、これらの追加のキーワードと語彙がサポートされることを期待してはなりません。実装は、サポートしていないキーワードを注釈として扱い、キーワードの値が注釈の値であるべきです。
実装は、直接サポートしていない語彙のハンドラーを登録またはロードする機能を提供してもよいです。そのようなハンドラーの登録および実装の正確なメカニズムは、実装に依存します。
JSONスキーマのキーワードは、いくつかの一般的な動作カテゴリに分類されます。アサーションは、インスタンスが制約を満たしていることを検証し、ブール値を結果として生成します。注釈は、アプリケーションが任意の方法で使用できる情報を添付します。アプリケータは、インスタンスの一部にサブスキーマを適用し、その結果を結合します。
拡張キーワードは、特に注釈が非常に柔軟であることを念頭に置いて、これらのカテゴリ内に留まるべきです。複雑な動作は通常、スキーマキーワードとして直接実装するよりも、注釈データに基づいてアプリケーションに委ねる方が適切です。ただし、拡張キーワードは、特別な目的のために他の動作を定義してもよいです。
スキーマに対するインスタンスの評価には、インスタンス内の適切な場所に対してスキーマ内のすべてのキーワードを処理することが含まれます。通常、アプリケータキーワードは、アプリケータ(したがってサブスキーマがない)がないスキーマオブジェクトに到達するまで処理されます。インスタンス内の適切な場所が、スキーマオブジェクト内のアサーションおよび注釈キーワードに対して評価され、その結果はアプリケータのルールに従って親スキーマに集められます。
親スキーマオブジェクトの評価は、すべての子スキーマが評価されると完了できますが、アサーションの結果によって評価が短絡される場合があります。注釈を収集している場合、一部のアサーション結果の短絡は、アサーションの結果をさらに変更できないものを含め、注釈収集のためにすべての子スキーマを調べる必要があるため、不可能です。
ほとんどのJSONスキーマのキーワードは単独で評価できますが、多くても同じスキーマオブジェクト内の隣接するキーワードの値または結果を考慮に入れる必要がある一方で、いくつかより複雑な動作をするものがあります。
キーワードのレキシカルスコープは、オブジェクトと配列のネストされたJSONデータ構造によって決定されます。最大のスコープは、スキーマドキュメント全体です。最小のスコープは、サブスキーマがない単一のスキーマオブジェクトです。
キーワードは、URI参照などの部分的な値で定義される場合があります。この値は、別のURI参照または完全なURIなど、JSONドキュメントのレキシカル構造を通じて見つかる別の値に対して解決する必要があります。「$id」、「$ref」、および「$dynamicRef」のコアキーワード、および「base」JSONハイパースキーマキーワードは、この種の動作の例です。
「$schema」などの一部のキーワードは、スキーマリソース全体のレキシカルスコープに適用されるため、スキーマリソースのルートスキーマにのみ出現する必要があります。
他のキーワードは、通常はインスタンスドキュメントとともに、スキーマの評価中に存在するダイナミックスコープを考慮に入れる場合があります。最も外側のダイナミックスコープは、処理が開始されるスキーマオブジェクトであり、スキーマリソースのルートでなくても構いません。このルートスキーマから特定のキーワードへのパス(解決された可能性のある「$ref」および「$dynamicRef」キーワードを含む)は、キーワードの「検証パス」と見なされます。
レキシカルスコープとダイナミックスコープは、参照キーワードが発生するまで揃っています。参照キーワードに従うと、処理は1つのレキシカルスコープから別のスコープに移動しますが、ダイナミックスコープの観点からは、参照に従うことは、値として存在するサブスキーマに降りていくのと変わりません。ダイナミックスコープを通じて情報を解決するその参照の反対側のキーワードは、ローカルのレキシカルに囲む親を調べるのではなく、参照の発信側をダイナミックな親と見なします。
ダイナミックスコープの概念は、主に「$dynamicRef」および「$dynamicAnchor」で使用され、高度な機能とみなされ、追加のキーワードを定義する際には注意して使用する必要があります。また、エラーおよび収集された注釈を報告する際にも表示されます。同じレキシカルスコープを異なるダイナミックスコープで繰り返し再訪できる可能性があるためです。このような場合、エラーまたは注釈を生成したダイナミックパスをユーザーに通知することが重要です。
キーワードの動作は、サブスキーマや隣接するキーワード(同じスキーマオブジェクト内のキーワード)とそのサブスキーマの注釈結果に関して定義してもよいです。そのようなキーワードは、循環依存関係を生じさせてはなりません。キーワードは、同じスキーマオブジェクト内の別のキーワードの存在または不在に基づいて動作を修正してもよいです。
欠落しているキーワードは、falseのアサーション結果を生成してはならず、注釈結果を生成してはならず、また、自身の動作定義の一部として、他のスキーマを評価させてはなりません。ただし、欠落しているキーワードは注釈を提供しないため、注釈結果がないと、他のキーワードの動作が間接的に変わる可能性があります。
場合によっては、キーワードの欠落時のアサーションの挙動が、特定の値によって生成される挙動と同一になることがあります。キーワード定義では、既知の場合にはそのような値を明記すべきです(SHOULD)。ただし、デフォルトの挙動を生み出す値が存在する場合、それが存在すれば注釈結果を生成するとしても、デフォルトの挙動は注釈を生成してはなりません(MUST NOT)。
注釈の収集は、計算量とメモリの両面で大きなコストを伴う可能性があるため、実装は、この機能をオプトアウトしてもよい(MAY)。収集された注釈に基づいて指定されるキーワードは、適切な場合には代替のアプローチを記述すべきです(SHOULD)。このアプローチは、このドキュメントの"items"および"additionalProperties"キーワードで示されています。
キーワードにそのような代替アプローチが不可能な場合、注釈コレクションをサポートしない実装は、それらのキーワードまたはそれらを含む語彙をサポートできないことに注意してください。
識別子は、スキーマの正規URIを設定するか、参照において、そのようなURIがどのように解決されるかに影響を与えるか、またはその両方を行います。このドキュメントで定義されているCore語彙では、いくつかの識別キーワード、特に "$id"が定義されています。
正規のスキーマURIは、インスタンスの処理中に変更してはなりません(MUST NOT)。ただし、URI参照の解決に影響を与えるキーワードは、実行時にのみ完全に決定される動作をする可能性があります。
カスタムの識別子キーワードは可能ですが、語彙の設計者は、コアキーワードの機能を中断しないように注意する必要があります。たとえば、この仕様の "$dynamicAnchor"キーワードは、そのURI解決効果を一致する"$dynamicRef"キーワードに限定し、"$ref"の動作を妨げないようにします。
アプリケータを使用すると、単一のスキーマオブジェクトでは実現できない、より複雑なスキーマを構築できます。スキーマドキュメントに対するインスタンスの評価は、完全なインスタンスドキュメントにルートスキーマを適用することから始まります。そこから、アプリケータと呼ばれるキーワードを使用して、適用される追加のスキーマを決定します。このようなスキーマは、現在の場所でインプレースで適用されることも、子ロケーションに適用されることもあります。
適用されるスキーマは、キーワードの値の全部または一部を構成するサブスキーマとして存在することがあります。あるいは、アプリケータは、同じスキーマドキュメント内の別の場所、または異なるスキーマドキュメント内のスキーマを参照する場合があります。このような参照されるスキーマを識別するメカニズムは、キーワードによって定義されます。
アプリケータキーワードは、サブスキーマまたは参照されるスキーマのブール値アサーションの結果を、どのように変更および/または組み合わせてアプリケータのブール値の結果を生成するかについても定義します。アプリケータは、サブスキーマのアサーション結果に任意のブール論理演算を適用できますが、独自のアサーション条件を導入してはなりません(MUST NOT)。
注釈の結果は、インスタンスの場所とスキーマキーワードの場所とともに保存されるため、アプリケーションは複数の値を解釈する方法を決定できます。
7.5節で述べたように、アプリケータキーワードは、アプリケータの値にサブスキーマとして含めるのではなく、適用されるスキーマを参照することがあります。このような状況では、適用されるスキーマは参照されるスキーマとして知られ、アプリケータキーワードを含むスキーマは参照するスキーマとして知られます。
ルートスキーマとサブスキーマは、スキーマドキュメント内のスキーマの位置に基づく静的な概念ですが、参照されるスキーマと参照するスキーマは動的です。さまざまなスキーマのペアが、インスタンスに対するスキーマの評価中に、さまざまな参照される配置と参照する配置になる可能性があります。
"$ref"などの参照による一部のアプリケータの場合、参照されるスキーマは、スキーマドキュメントの字句スコープの静的分析によって決定できます。 "$dynamicRef"("$dynamicAnchor"を使用)などの他のアプリケータは、動的スコープを使用する可能性があり、したがって、インスタンスでスキーマを評価するプロセスでのみ解決可能です。
JSONスキーマは、JSONドキュメントに対する制約をアサートするために使用でき、制約に合格するか失敗します。このアプローチを使用して、制約への適合性を検証したり、制約を満たすために必要なものをドキュメント化したりできます。
JSONスキーマの実装は、スキーマアサーションに対してインスタンスを評価するときに、単一のブール値の結果を生成します。
インスタンスは、スキーマに存在するアサーションにのみ失敗する可能性があります。
ほとんどのアサーションは、特定のプリミティブ型内の値のみを制約します。インスタンスの型がキーワードのターゲットとする型でない場合、インスタンスはアサーションに適合すると見なされます。
たとえば、コンパニオン検証語彙からの「maxLength」キーワードは、特定の文字列(長すぎる文字列)が有効になるのを制限するだけです。インスタンスが数値、ブール値、null、配列、またはオブジェクトの場合、このアサーションに対して有効です。
この動作により、キーワードを複数のプリミティブ型を持つ可能性のあるインスタンスでより簡単に使用できます。コンパニオン検証語彙には、インスタンスを1つ以上のプリミティブ型に独立して制限できる「type」キーワードも含まれています。これにより、特定の長さの文字列またはnull値を返す可能性のある関数のユースケースを簡潔に表現できます。
{ "type": ["string", "null"], "maxLength": 255 }
「maxLength」がインスタンス型を文字列に制限した場合、記述された例では実際にはnull値を許可しないため、これを表現するのは実質的により面倒になります。「maxLength」がインスタンスを文字列に制限する場合、「type」に「null」を含めても、有用な効果はありません。各キーワードは、特に指定しない限り、個別に評価されます。
JSONスキーマは、インスタンスが注釈を含むスキーマオブジェクトと、そのすべての上位スキーマオブジェクトに対して有効である場合は常に、インスタンスに情報を注釈を付けることができます。情報は、単純な値である場合もあれば、インスタンスの内容に基づいて計算できる場合もあります。
注釈は、インスタンス内の特定の場所に追加されます。多くのサブスキーマを任意の単一の場所に適用できるため、アプリケーションは、異なるスキーマオブジェクト内の同じスキーマキーワードによって、同じインスタンスの場所に付加される異なる注釈値をどのように処理するかを決定する必要がある場合があります。
アサーションの結果とは異なり、注釈データは、アプリケーションが適切と考えるように使用するために提供される、幅広い形式をとることができます。JSONスキーマの実装は、アプリケーションに代わって収集された情報を使用することは期待されていません。
特に指定がない限り、注釈キーワードの値は、キーワードの値です。ただし、他の動作も可能です。たとえば、JSONハイパースキーマの「links」キーワードは、インスタンスデータの一部に基づいて値を生成する複雑な注釈です。
アサーションでは「ショートサーキット」評価が可能ですが、注釈を収集するには、全体的なアサーションの結果を変更できない場合でも、インスタンスの場所に適用されるすべてのスキーマを調べる必要があります。唯一の例外は、検証に失敗したスキーマオブジェクトのサブスキーマは、注釈が失敗したスキーマに対して保持されないため、スキップされる場合があることです。
注釈は、注釈収集の動作を明示的に定義するキーワードによって収集されます。ブールスキーマはキーワードを使用しないため、注釈を生成できないことに注意してください。
収集された注釈には、次の情報を含める必要があります(MUST)。
アプリケーションは、値を提供したスキーマの場所に基づいて、使用する複数の注釈値のどれを優先するかを決定してもよい(MAY)。これは、柔軟な使用を可能にすることを目的としています。スキーマの場所を収集すると、そのような使用が容易になります。
たとえば、検証仕様からの注釈とアサーションを使用する次のスキーマを考えてみましょう。
いくつかの行は、わかりやすくするために折り返されています。
{ "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 } } }
この例では、フィーチャ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つの異なる値が存在することを、スキーマの場所に関係なくエラーと見なす場合があります。
falseのアサーション結果を生成するスキーマオブジェクトは、独自のキーワードからであれ、サブスキーマのキーワードからであれ、注釈結果を生成してはなりません(MUST NOT)。
スキーマ全体の注釈結果には、他のスキーマの場所から収集された注釈が含まれる場合があることに注意してください。このスキーマを考えると
{ "oneOf": [ { "title": "Integer Value", "type": "integer" }, { "title": "String Value", "type": "string" } ] }
インスタンス"これは文字列です"に対して、そのスキーマオブジェクトの型アサーションが失敗したため、「整数値」というタイトルの注釈は破棄されます。インスタンスが文字列型アサーションに合格するため、「文字列値」というタイトルの注釈は保持されます。
アプリケータキーワードは、独自の注釈結果を定義する可能性に加えて、サブスキーマまたは参照されるスキーマで収集された注釈を集約します。
4番目のキーワードのカテゴリは、スキーマ作成者にとって関心のある再利用可能なコンポーネントまたはデータを保持するために場所を予約するだけで、再利用には適していません。これらのキーワードは、検証または注釈の結果に影響を与えません。コア語彙でのそれらの目的は、特定の目的のために場所が利用可能であり、拡張キーワードによって再定義されないようにすることです。
これらのキーワードは結果に直接影響を与えるものではありませんが、9.4.2節で説明されているように、再利用可能なスキーマの場所を予約する認識されない拡張キーワードは、特定の状況下で参照との望ましくない相互作用を引き起こす可能性があります。
このドキュメントまたは関連ドキュメントの一部として定義された語彙の中に、インスタンスデータをターゲットにしたりロードしたりするキーワードはありませんが、他の語彙でそうしたい場合もあるかもしれません。
キーワードは、JSONポインターまたは相対JSONポインターを使用して、現在の評価場所の外側のインスタンスの一部を調べるように定義できます。
相対JSONポインターを使用して場所を調整できるキーワードは、デフォルトが必要な場合は、現在の場所を使用することをデフォルトにする必要があります。
このセクションで宣言されている、すべて「$」で始まるキーワードは、JSONスキーマコア語彙を構成します。これらのキーワードは、複数のドキュメントに分割されているものを含め、すべてのスキーマまたはメタスキーマを処理するために必須であるか、相互運用性を保証する必要がある目的のためにキーワードを予約するために存在します。
コア語彙は、さらに語彙を処理するためのブートストラップとして、常に必須であるとみなす必要があります。"$vocabulary"キーワードを使用して使用中の語彙を宣言するメタスキーマは、コア語彙を明示的にリストする必要があり、必須であることを示すtrueの値を持つ必要があります。
この語彙(およびこの語彙のみ)のfalse値の動作は未定義であり、「$vocabulary」が存在するがコア語彙が含まれていない場合の動作も未定義です。ただし、実装ではこれらのケースを検出し、発生した場合はエラーを発生させることが推奨されます。メタスキーマがコアをオプションで使用すると宣言することは意味がありません。
「$vocabulary」を使用しないメタスキーマは、そのURIがtrueの値で存在する場合と同様に、コア語彙を必要とするとみなす必要があります。
コア語彙の現在のURIは、<https://json-schema.dokyumento.jp/draft/2020-12/vocab/core>です。
対応するメタスキーマの現在のURIは、<https://json-schema.dokyumento.jp/draft/2020-12/meta/core>です。
「$」プレフィックスは正式にはコア語彙用に予約されていませんが、拡張キーワード(語彙またはそれ以外)は、将来の競合を避けるために「$」以外の文字で始めることが推奨されます。
メタスキーマと語彙という2つの概念は、スキーマを解釈する方法を実装に通知するために使用されます。すべてのスキーマにはメタスキーマがあり、「$schema」キーワードを使用して宣言できます。
メタスキーマは2つの目的を果たします
メタスキーマは、語彙をさまざまな方法で組み合わせたり、メタスキーマの作成者が特定のキーワードを禁止したり、開発およびテストサイクル中に実行されるような、通常よりも厳密な構文検証を実行したりするなど、追加の制約を課したりできるように、語彙とは別に存在します。各語彙は通常、語彙のキーワードのみで構成されるメタスキーマを識別します。
メタスキーマの作成はJSONスキーマの高度な使用法であるため、メタスキーマ機能の設計では、シンプルさよりも柔軟性が重視されています。
「$schema」キーワードは、JSONスキーマの方言識別子として、また、この特定の方言で記述された有効なスキーマのセットを記述するJSONスキーマ自体であるリソースの識別子として使用されます。
このキーワードの値は、URI(スキームを含む)である必要があり、このURIは正規化されている必要があります。現在のスキーマは、このURIによって識別されるメタスキーマに対して有効である必要があります。
このURIが取得可能なリソースを識別する場合、そのリソースはメディアタイプ「application/schema+json」である必要があります。
「$schema」キーワードは、ドキュメントルートスキーマオブジェクトで使用する必要があり、埋め込みスキーマリソースのルートスキーマオブジェクトで使用できます。リソースルートではないスキーマオブジェクトには表示されてはなりません。ドキュメントルートスキーマにない場合、結果の動作は実装定義です。
このプロパティの値は、このドキュメントおよび他のドキュメント、および他の当事者によって定義されます。
「$vocabulary」キーワードは、メタスキーマで、そのメタスキーマで記述されたスキーマで使用できる語彙を識別するために使用されます。また、スキーマを正常に処理するために、実装が必須語彙を理解する必要があるという意味で、各語彙が必須かオプションかを示すためにも使用されます。この情報全体で方言を形成します。実装によって理解される語彙は、語彙に含まれるセマンティック定義と一致する方法で処理する必要があります。
このキーワードの値はオブジェクトである必要があります。オブジェクトのプロパティ名はURI(スキームを含む)である必要があり、このURIは正規化されている必要があります。プロパティ名として表示される各URIは、特定のキーワードセットとそのセマンティクスを識別します。
URIはURLでもかまいませんが、取得可能なリソースの性質は現在未定義であり、将来の使用のために予約されています。語彙の作成者は、語彙URIとして、text/htmlやtext/plainなどの人間が読めるメディアタイプで、語彙仕様のURLを使用できます。[CREF1]語彙ドキュメントは今後のドラフトで追加される可能性があります。今のところ、キーワードセットを特定することが十分であるとみなされます。メタスキーマの検証とともに、それが現在の「語彙」の動作方法です。将来の語彙ドキュメント形式はJSONドキュメントとして指定されるため、今のところtext/htmlなどの非JSON形式を使用しても、将来のあいまいさは生じません。
オブジェクトプロパティの値はブール値である必要があります。値がtrueの場合、語彙を認識しない実装は、「$schema」でこのメタスキーマを宣言するスキーマの処理を拒否する必要があります。値がfalseの場合、語彙を認識しない実装は、そのようなスキーマの処理を進める必要があります。実装が語彙を理解している場合、値は影響を与えません。
6.5に従い、認識されないキーワードは注釈として扱われる必要があります。これは、認識されない語彙で定義されたキーワードにも当てはまります。語彙で定義されている認識されないキーワードと、語彙の一部ではないキーワードを区別することは現在不可能です。
「$vocabulary」キーワードは、メタスキーマとして使用することを目的としたスキーマドキュメントのルートスキーマで使用する必要があります。サブスキーマには表示されてはなりません。
「$vocabulary」キーワードは、メタスキーマとして処理されていないスキーマドキュメントでは無視する必要があります。これにより、バリデーターがMによって宣言された語彙を理解することを要求せずに、メタスキーマMをそれ自身のメタスキーマM'に対して検証できます。
「$vocabulary」が存在しない場合、実装は、参照スキーマの「$schema」キーワードのURI値から認識された場合は、メタスキーマに基づいて動作を決定できます。これは、(Hyper-Schemaの使用など)語彙の存在前に動作が認識されていた方法です。
スキーマによって参照されるメタスキーマが認識されないか、存在しない場合、動作は実装定義です。実装がスキーマの処理を続行する場合、コア語彙を使用することを想定する必要があります。実装が特定の目的のために構築されている場合は、その目的の最も関連性の高いすべての語彙を使用することを想定する必要があります。
たとえば、バリデーターである実装は、この仕様およびコンパニオン検証仕様のすべての語彙を使用することを想定する必要があります。
「$vocabulary」の処理制限は、「$ref」または類似のキーワードを使用して他のメタスキーマを参照するメタスキーマが、他のメタスキーマの語彙宣言を自動的に継承しないことを意味することに注意してください。このような宣言はすべて、メタスキーマとして使用することを目的とした各スキーマドキュメントのルートで繰り返す必要があります。これは、メタスキーマの例で示されています。[CREF2]この要件により、実装は各メタスキーマの単一の場所ですべての語彙要件情報を見つけることができます。スキーマの拡張性は、参照によってより詳細なメタスキーマを組み合わせる無限の潜在的な方法があることを意味するため、実装がすべての可能性を予期し、参照されるメタスキーマで語彙を検索するように要求すると、過度に負担がかかる可能性があります。
エラーを修正するために、仕様のドラフト間で更新された語彙およびメタスキーマURIが公開される場合があります。実装では、この仕様のドラフト以降、次の仕様のドラフトより前の日付のURIは、ここにリストされているものと同じ構文とセマンティクスを示すと見なす必要があります。
広大なエコシステム内のスキーマを区別するために、スキーマはURIで識別され、そのURIを指定することで他のスキーマへの参照を埋め込むことができます。
いくつかのキーワードは、相対URI参照、または相対URI参照を構築するために使用される値を受け入れることができます。これらのキーワードでは、参照を解決するためにベースURIを確立する必要があります。
「$id」キーワードは、正規 URIを使用してスキーマリソースを識別します。
このURIは識別子であり、必ずしもネットワークロケーターではないことに注意してください。ネットワークアドレス指定可能なURLの場合、スキーマはその正規URIからダウンロード可能である必要はありません。
存在する場合、このキーワードの値は文字列でなければならず、有効なURI参照を表す必要があります。このURI参照は正規化されるべきであり、絶対URI(フラグメントなし)に解決される必要があります。したがって、"$id"には空でないフラグメントを含めてはならず、空のフラグメントを含めるべきではありません。
application/schema+jsonメディアタイプのコンテキストにおける空のフラグメントは、フラグメントなしのベースURIと同じリソースを参照するため、実装は、空のフラグメントで終わるURIをフラグメントを削除することで正規化してもよいでしょう。ただし、スキーマ作成者は、実装間でのこの動作に依存すべきではありません。[CREF3]これは主に、古いメタスキーマの$id(または以前のid)に空のフラグメントがあるため許可されています。将来のドラフトでは、$idに空のフラグメントさえも完全に禁止する可能性があります。
このURIはまた、スキーマリソース内のキーワード内の相対URI参照のベースURIとしても機能します。RFC 3986セクション5.1.1の、コンテンツに埋め込まれたベースURIに関する規定に従います。
サブスキーマに"$id"が存在することは、そのサブスキーマが単一のスキーマドキュメント内で個別のスキーマ リソースを構成することを示します。さらに、RFC 3986セクション5.1.2の、エンティティのカプセル化に関する規定に従い、サブスキーマの"$id"が相対URI参照である場合、その参照を解決するためのベースURIは、親スキーマ リソースのURIとなります。
親スキーマオブジェクトが"$id"でリソースとして明示的に識別されない場合、ベースURIは、前のセクションで示された手順に従って確立される、ドキュメント全体のURIになります。
JSONスキーマドキュメントのルートスキーマは、スキームを含むがフラグメントのない絶対URIを持つ"$id"キーワードを含むべきです。
JSONポインターフラグメントを使用するには、スキーマの構造に関する知識が必要です。再利用可能なスキーマを提供することを目的としてスキーマドキュメントを作成する場合、特定の構造上の場所に関連付けられていない、プレーンな名前フラグメントを使用することが好ましい場合があります。これにより、JSONポインター参照を更新する必要なく、サブスキーマを再配置できます。
「$anchor」および「$dynamicAnchor」キーワードは、このようなフラグメントを指定するために使用されます。これらは、"$id"で見られる絶対URIではなく、プレーンな名前フラグメントを作成するためにのみ使用できる識別子キーワードです。
結果のフラグメントが追加されるベースURIは、問題の「$anchor」または「$dynamicAnchor」を含むスキーマ リソースの正規URIです。前のセクションで説明したように、これは同じまたは親スキーマオブジェクト内の最も近い"$id"、またはRFC 3986に従って決定されるドキュメントのベースURIのいずれかです。
URIの通常の用途とは別に、「$dynamicAnchor」は、「$dynamicRef」キーワードと組み合わせて使用した場合、フラグメントが拡張ポイントであることを示します。この低レベルの高度な機能により、メタスキーマなどの再帰的スキーマを拡張しやすくなります。この拡張に特定のセマンティクスを課すことはありません。詳細については、"$dynamicRef"に関するセクションを参照してください。
ほとんどの場合、通常のフラグメントの動作で十分であり、より直感的です。したがって、「$dynamicAnchor」が明確に必要な場合を除き、「$anchor」を使用してプレーンな名前フラグメントを作成することが推奨されます。
存在する場合、このキーワードの値は文字列でなければならず、文字([A-Za-z])またはアンダースコア("_")で始まり、その後に任意の数の文字、数字([0-9])、ハイフン("-")、アンダースコア("_")、およびピリオド(".")が続く必要があります。これは、XMLのNCName生成のUS-ASCII部分と一致します。[CREF4]アンカー文字列にはURI参照ではないため、「#」文字は含まれていないことに注意してください。「$anchor": "foo" は、URIで使用されるとフラグメント「#foo」になります。完全な例については、以下を参照してください。
同じリソース内で、「$anchor」または「$dynamicAnchor」の任意の組み合わせを使用して、同じフラグメント名を複数回指定した場合の効果は未定義です。実装は、そのような使用が検出された場合、エラーを発生させる可能性があります。
いくつかのキーワードを使用して、現在のインスタンスの場所に適用されるスキーマを参照できます。「$ref」と「$dynamicRef」は、参照されるスキーマをインスタンスに適用するアプリケーターキーワードです。
「$ref」および「$dynamicRef」の値はURI参照であるため、スキーマを複数のファイルに外部化または分割することができ、自己参照を通じて再帰的な構造を検証する機能を提供します。
これらのキーワードによって生成される解決済みのURIは、必ずしもネットワークロケーターではなく、単なる識別子です。スキーマがネットワークアドレス可能なURLである場合、アドレスからダウンロードできる必要はなく、実装はネットワークアドレス可能なURIに遭遇した場合にネットワーク操作を実行する必要があると想定すべきではありません。
「$ref」キーワードは、静的に識別されたスキーマを参照するために使用されるアプリケーターです。その結果は、参照されたスキーマの結果です。[CREF5]結果がどのように決定されるかのこの定義は、同じスキーマオブジェクトで「$ref」と一緒に他のキーワードが表示される可能性があることを意味することに注意してください。
「$ref」キーワードの値は、URI参照である文字列でなければなりません。現在のURIベースに対して解決されると、適用するスキーマのURIが生成されます。インスタンスの評価プロセスによって参照の解決方法を変更できないため、この解決はスキーマのロード時に安全に実行できます。
「$dynamicRef」キーワードは、実行時まで完全な解決を延期できるようにするアプリケーターであり、インスタンスを評価中に遭遇するたびに解決されます。
「$dynamicAnchor」とともに、「$dynamicRef」は、主に再帰的スキーマ(それ自体を参照するスキーマ)で役立つ協調的な拡張メカニズムを実装します。拡張ポイントと実行時に決定される拡張ターゲットの両方が「$dynamicAnchor」で定義され、「$dynamicRef」で参照された場合にのみ、実行時の動的動作を示します。
「$dynamicRef」プロパティの値は、URI参照である文字列でなければなりません。現在のURIベースに対して解決されると、実行時解決の開始点として使用されるURIが生成されます。この初期解決は、スキーマのロード時に安全に実行できます。
最初に解決された開始点URIに、「$dynamicAnchor」キーワードによって作成されたフラグメントが含まれている場合、最初のURIは、「$dynamicAnchor」を使用して同一の名前のフラグメントを定義する動的スコープ内の最も外側のスキーマ リソースのURI(フラグメントを含む)に置き換える必要があります。
それ以外の場合、その動作は「$ref」と同じであり、実行時の解決は必要ありません。
これらのキーワードを使用した完全な例については、付録Cを参照してください。[CREF6]2019年以前のドラフトのハイパースキーマメタスキーマとこのドラフトの違いは、これらのキーワードの有用性を劇的に示しています。
「$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では、ドキュメントのデフォルトのベースURIを決定する方法を定義しています。
参考までに、スキーマの初期ベースURIは、ネットワークロケーション、ローカルファイルシステム、または既知のスキームのURIで識別できるその他の状況に関係なく、スキーマが見つかったURIです。
スキーマドキュメントが"$id"(コンテンツに埋め込まれている)で明示的なベースURIを定義していない場合、ベースURIはRFC 3986セクション5に従って決定されます。
ソースが不明な場合、またはソースに既知のURIスキームがない場合は、RFC 3986セクション5.1.4で説明されているように、適切な実装固有のデフォルトURIを使用してもよいでしょう。実装が想定するデフォルトのベースURIを文書化することが推奨されます。
スキーマオブジェクトが別のメディアタイプのドキュメントに埋め込まれている場合、初期ベースURIは、そのメディアタイプのルールに従って決定されます。
次のセクションで説明する「$id」キーワードがルートスキーマに存在しない限り、このベースURIは、スキーマドキュメントのルートスキーマ リソースの正規URIと見なされるべきです。
リモートスキーマを識別するためにURIを使用することは、必ずしも何もダウンロードされないことを意味するのではなく、代わりにJSONスキーマ実装は、使用するスキーマと、それらを識別するURIを事前に理解しておく必要があります。
たとえば、どのスキーマをダウンロードするかを実行時まで知らない汎用ユーザーエージェントによってスキーマがダウンロードされる場合は、ハイパーメディアの使用を参照してください。
実装は、検証ツールがスキーマに対して持っている信頼に応じて、任意のURIを任意のスキーマに関連付けたり、スキーマの「$id」で指定されたURIを自動的に関連付けたりできる必要があります。そのようなURIとスキーマは、インスタンスを処理する前に実装に提供することも、処理中にスキーマドキュメント内で指摘して、付録Aに示すような関連付けを生成することもできます。
スキーマには複数のURIがある可能性があります(可能性が高い)が、URIが複数のスキーマを識別する方法はありません。複数のスキーマが同じURIとして識別しようとすると、検証ツールはエラー状態を発生させる必要があります。
実装は、別のスキーマの "$schema" キーワードによってメタスキーマとして識別されたために検査される場合、スキーマをメタスキーマとして認識しなければなりません(MUST)。これは、単一のスキーマ文書が、ある時は通常のスキーマと見なされ、別の時にはメタスキーマと見なされる可能性があることを意味します。
それ自身のメタスキーマであるスキーマを検査する場合、実装がそれを通常のスキーマとして処理し始めると、その規則の下で処理されます。しかし、自身の "$schema" 値のチェックの結果として2回目にロードされた場合、それはメタスキーマとして扱われます。したがって、同じ文書が1つのセッションの中で両方の方法で処理されます。
実装は、実装固有の目的(例えば、一般的に使用されるメタスキーマを事前にロードしたり、その語彙サポート要件を事前に確認したりするなど)のために、スキーマを明示的にメタスキーマとして渡すことを許可してもよい(MAY)。メタスキーマの作成者は、そのような機能が実装間で相互運用可能であることを期待してはなりません(MUST NOT)。
スキーマは、JSONポインタまたは "$id" によって直接与えられたURIを含む、与えられた任意のURIによって識別できます。すべての場合において、"$ref" 参照をデリファレンスするには、最初に RFC 3986 に従って、その値を現在のベースURIに対するURI参照として解決する必要があります。
結果のURIが、現在の文書内、または実装で利用可能になっている別のスキーマ文書内のスキーマを識別する場合、そのスキーマは自動的に使用されるべきです(SHOULD)。
例えば、このスキーマを考えてみましょう。
{ "$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に対して "$anchor" 値をフラグメント名として解決し、<https://example.net/root.json#item> を形成します。
実装が次に <#/items> スキーマ内を見ると、<#item> 参照に遭遇し、これを <https://example.net/root.json#item> に解決します。これは同じ文書で定義されていることがわかっているため、自動的に使用できます。
実装が "other.json" への参照に遭遇すると、これを <https://example.net/other.json> に解決しますが、これはこの文書では定義されていません。その識別子を持つスキーマが実装に別途提供されている場合、それも自動的に使用できます。[CREF7]参照されたスキーマが不明な場合、実装はどうすべきでしょうか?自動ネットワークデリファレンスが許可される状況はありますか?同一オリジンポリシー?ユーザー設定可能なオプション?Hyper-Schemaによって記述された進化するAPIの場合、新しいスキーマがシステムに動的に追加されることが予想されるため、スキーマ文書の事前ロードを絶対的な要件とすることは現実的ではありません。
JSONポインタURIフラグメントは、スキーマ文書の構造に基づいて構築されるため、埋め込まれたスキーマリソースとそのサブスキーマは、独自の正規URI、または包含リソースのURIに対して相対的なJSONポインタフラグメントによって識別できます。
概念的には、リンクされたスキーマリソースのセットは、各リソースが スキーマ参照で接続された別々の文書であるか、1つ以上のスキーマリソースがサブスキーマとして埋め込まれた単一の文書として構造化されているかどうかにかかわらず、同一に動作する必要があります。
親スキーマリソースのURIに相対的なJSONポインタフラグメントを含むURIは、埋め込まれたスキーマが別の文書に移動して参照されると無効になるため、アプリケーションとスキーマは、そのようなURIを埋め込まれたスキーマリソースまたはその中の場所を識別するために使用するべきではありません(SHOULD NOT)。
以下に、別のスキーマリソースが埋め込まれているスキーマ文書を考えます。
{ "$id": "https://example.com/foo", "items": { "$id": "https://example.com/bar", "additionalProperties": { } } }
URI "https://example.com/foo#/items/additionalProperties" は、埋め込まれたリソースの "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)。非正規URIを使用すると、スキーマの相互運用性が低下する可能性があるためです。[CREF8]これは、スキーマリソースが再編成された場合に、すべてが脆弱になるため、実装が可能性のあるベースURIとJSONポインタフラグメントのスタック全体を追跡することを要求しないようにするためです。簡単なので禁止する必要はないと主張する人もいれば、スキーマの識別を複雑にするため禁止すべきだと主張する人もいます。このトピックに関するフィードバックが推奨されます。
そのような非正規URIのさらなる例と、代わりに使用する適切な正規URIは、付録Aに提供されています。
複合スキーマ文書は、輸送を容易にするために複数の埋め込みJSONスキーマリソースが同じ文書にバンドルされたJSON文書(「バンドルされた」スキーマとも呼ばれる)として定義されます。
各埋め込みスキーマリソースは、語彙サポートの決定を含め、標準のスキーマのロードおよび処理要件に従って、個々のスキーマリソースとして扱われなければなりません(MUST)。
複合スキーマ文書を作成するためのバンドルプロセスは、外部スキーマリソースへの参照("$ref" など)を取得し、参照されたスキーマリソースを参照元の文書内に埋め込むこととして定義されます。バンドルは、ベース文書および参照/埋め込み文書で使用されるすべてのURI(参照に使用)が変更を必要としない方法で行われるべきです(SHOULD)。
各埋め込みJSONスキーマリソースは、スキーマリソースのルートで "$id" キーワードを使用してそれ自身をURIで識別しなければなりません(MUST)。また、使用しているダイアレクトを識別するために "$schema" キーワードを使用するべきです(SHOULD)。 "$id" のURI識別子値は絶対URIであることが推奨されます(RECOMMENDED)。
参照によるアプリケータによって参照されるスキーマリソースがバンドルされる場合、スキーマリソースは、包含スキーマのルートにある "$defs" オブジェクトの値として配置されることが推奨されます(RECOMMENDED)。現在埋め込まれているスキーマリソースの "$defs" のキーは、バンドルされたスキーマの "$id"、またはアプリケーション定義の一意の識別子(UUIDなど)の形式にすることができます。このキーは、JSONスキーマで参照されることを意図していませんが、アプリケーションがバンドルプロセスを支援するために使用できます。
スキーマリソースは、場所がスキーマ値として定義されている "$defs" 以外の場所に埋め込んでもよい(MAY)。
バンドルされたスキーマリソースは、参照元のスキーマオブジェクトを置き換えたり、他のアプリケータキーワードでスキーマリソースをラップしたりすることによってバンドルしてはなりません(MUST NOT)。
同一の出力を生成するために、以前に外部にあったスキーマリソースへの包含スキーマ文書内の参照は変更してはならず(MUST NOT)、埋め込まれたスキーマリソースの "$id" を使用してスキーマに解決されるようになりました。そのような同一の出力には、検証評価、および結果として得られる注釈またはエラーで使用されるURIまたはパスが含まれます。
バンドルプロセスは複合スキーマ文書を作成する主な方法となることが多いですが、以前に独自の個々のスキーマリソースが存在せずに、手動で作成されることも可能であり、予想されます。
複数のスキーマリソースが1つの文書に存在する場合、処理に使用するダイアレクトを定義しないスキーマリソースは、囲むリソースと同じダイアレクトで処理しなければなりません(MUST)。
参照できるスキーマはすべて埋め込むこともできるため、埋め込まれたスキーマリソースは、囲むリソースの "$schema" 値を使用して異なる処理ダイアレクトを指定してもよい(MAY)。
複合スキーマ文書には、異なるダイアレクトを使用していると識別される埋め込みリソースが含まれている可能性があるため、これらの文書は、インスタンスとして複合スキーマ文書にメタスキーマを適用することによって検証するべきではありません(SHOULD NOT)。スキーマ文書を検証するために代替検証プロセスを提供することが推奨されます(RECOMMENDED)。各スキーマリソースは、関連付けられたメタスキーマに対して個別に検証されるべきです(SHOULD)。 [CREF9]スキーマが検証対象であることを知っている場合は、文書のルート以外で使用されている場合は埋め込みリソースを識別する "$id" を使用することで、スキーマが複合スキーマ文書であるかどうかを識別できます。
すべての埋め込みリソースが同じダイアレクトを使用していると識別するか、"$schema" が省略されて囲むリソースのデフォルトになる複合スキーマ文書は、適切なメタスキーマを適用して検証してもよい(MAY)。
スキーマは、インスタンスに対して無限ループに陥ってはなりません(MUST NOT)。たとえば、2つのスキーマ "#alice" と "#bob" の両方に、もう一方を参照する "allOf" プロパティがある場合、ナイーブなバリデーターはインスタンスを検証しようとして無限の再帰ループにスタックする可能性があります。スキーマは、このような無限の再帰ネストを使用するべきではありません(SHOULD NOT)。動作は未定義です。
サブスキーマオブジェクト(またはブール値)は、既知のアプリケータキーワードまたは "$defs" のような1つ以上のサブスキーマを値として受け取る場所予約キーワードでの使用によって認識されます。これらのキーワードは、"$defs"、およびこの文書からの標準アプリケータ、または既知の語彙からの拡張キーワード、または実装固有のカスタムキーワードである可能性があります。
不明なキーワードのマルチレベル構造は、ネストされたサブスキーマを導入する可能性があり、これは "$id" の処理規則の対象になります。したがって、そのような認識されない構造での参照先は、信頼できる方法で実装することはできず、結果の動作は未定義です。同様に、値がスキーマではないことがわかっている既知のキーワードでの参照先は、実装にそのようなターゲットを検出する必要性を負担させないようにするために、未定義の動作になります。[CREF10]これらのシナリオは、HTTP経由でスキーマを取得するが、Content-Typeがapplication/schema+json以外の応答を受信することに似ています。実装は確かにそれをスキーマとして解釈しようとすることができますが、オリジンサーバーはそれが実際にそのようなものであるという保証を提供していません。したがって、それをそのようなものとして解釈することにはセキュリティ上の意味合いがあり、予測不可能な結果が生じる可能性があります。
"$defs" と同じ構文とセマンティクスを持つ単一レベルのカスタムキーワードは、介入する "$id" キーワードを許可しないため、参照先をスキーマとして使用しようとする実装の下で正しく動作します。ただし、この動作は実装固有であり、相互運用性のために信頼してはなりません(MUST NOT)。
JSONは、自動APIとロボットのためにHTTPサーバーによって広く採用されてきました。このセクションでは、メディアタイプと Webリンクをサポートするプロトコルで使用する場合に、よりRESTfulな方法でJSON文書の処理を強化する方法について説明します。
スキーマによって記述されるインスタンスは、Linked Data Protocol 1.0、セクション8.1で定義されているように、"describedby" というリンク関係を使用してダウンロード可能な JSON Schema へのリンクを提供することが推奨されます。
HTTP では、このようなリンクはLink ヘッダーを使用して任意のリクエストに添付できます。このようなヘッダーの例は以下のようになります。
Link: <https://example.com/my-hyper-schema>; rel="describedby"
ネットワーク上のハイパーメディアシステムで使用する場合、スキーマを配布するプロトコルとして、HTTPが頻繁に選択されます。クライアントが、スキーマを長期間キャッシュできるにもかかわらず、必要以上に頻繁にネットワーク経由でスキーマをプルすると、サーバー管理者に問題が発生する可能性があります。
HTTP サーバーは、JSON Schema に長期間のキャッシュヘッダーを設定する必要があります。HTTP クライアントは、キャッシュヘッダーを監視し、鮮度期間内にドキュメントを再リクエストすべきではありません。分散システムは、共有キャッシュやキャッシュプロキシを使用する必要があります。
クライアントは、JSON Schema の実装またはソフトウェア製品に固有の User-Agent ヘッダーを設定またはプリペンドする必要があります。記号は重要度の高い順に並べられるため、JSON Schema ライブラリの名前/バージョンは、より一般的な HTTP ライブラリの名前(存在する場合)よりも前に配置する必要があります。例:
User-Agent: product-name/5.4.1 so-cool-json-schema/1.0.2 curl/7.43.0
クライアントは、サーバーオペレーターが潜在的に誤った動作をしているスクリプトの所有者に連絡できるように、"From" ヘッダーを使用してリクエストを作成できるようにする必要があります。
このセクションでは、他の語彙の基礎として使用することが推奨される、アプリケーターキーワードの語彙を定義します。
「$vocabulary」を使用しないメタスキーマは、その URI が true の値で存在するかのように、この語彙を必須とみなす必要があります。
アプリケーター語彙として知られるこの語彙の現在の URI は、 <https://json-schema.dokyumento.jp/draft/2020-12/vocab/applicator> です。
対応するメタスキーマの現在の URI は、<https://json-schema.dokyumento.jp/draft/2020-12/meta/applicator> です。
エラーを修正するために、仕様のドラフト間で更新された語彙およびメタスキーマURIが公開される場合があります。実装では、この仕様のドラフト以降、次の仕様のドラフトより前の日付のURIは、ここにリストされているものと同じ構文とセマンティクスを示すと見なす必要があります。
スキーマキーワードは通常、互いの結果に影響を与えることなく、独立して動作します。
スキーマ作成者の便宜のために、この語彙のキーワードにはいくつかの例外があります。
これらのキーワードは、親スキーマが適用されているインスタンスと同じ場所にサブスキーマを適用します。これらを使用すると、サブスキーマの結果をさまざまな方法で組み合わせたり変更したりできます。
これらのキーワードのサブスキーマは、インスタンスを完全に独立して評価します。そのため、1つのサブスキーマの結果が兄弟サブスキーマの結果に影響を与えることはありません。したがって、サブスキーマは任意の順序で適用できます。
これらのキーワードは、サブスキーマのブール値のアサーション結果を結合または変更するための論理演算子に対応します。これらは、アノテーションコレクションに直接的な影響を与えませんが、同じアノテーションキーワードを異なる値でインスタンスの場所に適用できるようにします。アノテーションキーワードは、そのような値を結合するための独自のルールを定義します。
このキーワードの値は、空でない配列である必要があります。配列の各項目は、有効な JSON Schema である必要があります。
インスタンスは、このキーワードの値によって定義されたすべてのスキーマに対して正常に検証された場合、このキーワードに対して正常に検証されます。
このキーワードの値は、空でない配列である必要があります。配列の各項目は、有効な JSON Schema である必要があります。
インスタンスは、このキーワードの値によって定義された少なくとも1つのスキーマに対して正常に検証された場合、このキーワードに対して正常に検証されます。アノテーションが収集されている場合、正常に検証される各サブスキーマからアノテーションが収集されるように、すべてのサブスキーマを調べる必要があることに注意してください。
このキーワードの値は、空でない配列である必要があります。配列の各項目は、有効な JSON Schema である必要があります。
インスタンスは、このキーワードの値によって定義された正確に1つのスキーマに対して正常に検証された場合、このキーワードに対して正常に検証されます。
このキーワードの値は、有効な JSON Schema である必要があります。
インスタンスは、このキーワードによって定義されたスキーマに対して正常に検証されない場合、このキーワードに対して有効です。
これらのキーワードのうち3つは連携して、別のサブスキーマの結果に基づいてサブスキーマの条件付き適用を実装します。4番目は、特定の条件付きケースのショートカットです。
"if"、"then"、および "else" は、サブスキーマの境界を越えて相互に作用してはなりません。言い換えれば、"allOf" の1つのブランチの "if" が、別のブランチの "then" または "else" に影響を与えてはなりません。
"if"、"then"、または "else" が存在しない場合のデフォルトの動作はありません。特に、空のスキーマが存在する場合のように扱われるべきではなく、"if" が存在しない場合、"then" と "else" の両方が完全に無視される必要があります。
このキーワードの値は、有効な JSON Schema である必要があります。
このキーワードのサブスキーマの検証結果は、全体的な検証結果に直接的な影響を与えません。むしろ、"then" または "else" キーワードのどちらが評価されるかを制御します。
このキーワードのサブスキーマに対して正常に検証されたインスタンスは、存在する場合は、"then" キーワードのサブスキーマ値に対しても有効である必要があります。
このキーワードのサブスキーマに対して検証に失敗したインスタンスは、存在する場合は、"else" キーワードのサブスキーマ値に対しても有効である必要があります。
アノテーションが収集されている場合、キーワードが "then" または "else" のどちらもなしで存在する場合を含め、通常の方法でこのキーワードのサブスキーマから収集されます。
このキーワードの値は、有効な JSON Schema である必要があります。
"if" が存在し、インスタンスがそのサブスキーマに対して正常に検証された場合、インスタンスがこのキーワードのサブスキーマに対して正常に検証された場合、このキーワードに対して検証が成功します。
このキーワードは、"if" が存在しない場合、またはインスタンスがそのサブスキーマに対して検証に失敗した場合は効果がありません。実装では、このような場合、検証またはアノテーション収集の目的で、このキーワードに対してインスタンスを評価してはなりません。
このキーワードの値は、有効な JSON Schema である必要があります。
"if" が存在し、インスタンスがそのサブスキーマに対して検証に失敗した場合、インスタンスがこのキーワードのサブスキーマに対して正常に検証された場合、このキーワードに対して検証が成功します。
このキーワードは、"if" が存在しない場合、またはインスタンスがそのサブスキーマに対して正常に検証された場合は効果がありません。実装では、このような場合、検証またはアノテーション収集の目的で、このキーワードに対してインスタンスを評価してはなりません。
このキーワードは、インスタンスがオブジェクトであり、特定のプロパティが含まれている場合に評価されるサブスキーマを指定します。
このキーワードの値はオブジェクトである必要があります。オブジェクトの各値は、有効な JSON Schema である必要があります。
オブジェクトキーがインスタンス内のプロパティである場合、インスタンス全体がサブスキーマに対して検証される必要があります。その使用は、プロパティの存在に依存します。
このキーワードを省略すると、空のオブジェクトと同じ動作になります。
これらの各キーワードは、そのサブスキーマを子インスタンス、特にオブジェクトプロパティと配列項目に適用し、その結果を結合するためのルールを定義します。
"prefixItems" の値は、有効な JSON Schema の空でない配列である必要があります。
インスタンスの各要素が、同じ位置にあるスキーマ(存在する場合)に対して検証された場合、検証は成功します。このキーワードは、配列の長さを制約しません。配列がこのキーワードの値よりも長い場合、このキーワードは、一致する長さのプレフィックスのみを検証します。
このキーワードは、このキーワードがサブスキーマを適用した最大のインデックスであるアノテーション値を生成します。値は、"items" キーワードによって生成されるように、サブスキーマがインスタンスのすべてのインデックスに適用された場合はブール値 true になる場合があります。このアノテーションは、"items" および "unevaluatedItems" の動作に影響を与えます。
このキーワードを省略すると、空の配列と同じアサーション動作になります。
"items" の値は、有効な JSON Schema である必要があります。
このキーワードは、同じスキーマオブジェクト内の "prefixItems" 配列の長さよりも大きいインデックスのすべてのインスタンス要素にそのサブスキーマを適用します。これは、その "prefixItems" キーワードのアノテーション結果によって報告されます。そのようなアノテーション結果が存在しない場合、"items" はそのサブスキーマをすべてのインスタンス配列要素に適用します。[CREF11]"prefixItems" なしの "items" の動作は、以前のドラフトの "items" のスキーマ形式の動作と同じであることに注意してください。 "prefixItems" が存在する場合、"items" の動作は以前の "additionalItems" キーワードと同じです。
"items" サブスキーマがインスタンス配列内の任意の位置に適用される場合、ブール値 true のアノテーション結果を生成します。これは、残りのすべての配列要素がこのキーワードのサブスキーマに対して評価されたことを示します。
このキーワードを省略すると、空のスキーマと同じアサーション動作になります。
実装では、"prefixItems" 配列の存在とサイズを直接確認するなど、同じ効果を生み出す別の方法でこのキーワードを実装または最適化することを選択できます。アノテーションコレクションをサポートしない実装は、そうする必要があります。
このキーワードの値は、有効な JSON Schema である必要があります。
配列インスタンスは、少なくとも1つの要素が指定されたスキーマに対して有効な場合、"contains" に対して有効です。他のキーワードで使用するアノテーションを収集するために、最初のマッチが見つかった後でも、サブスキーマをすべての配列要素に適用する必要があります。これは、可能なすべてのアノテーションが収集されるようにするためです。
論理的には、配列内の各項目に値サブスキーマを適用した検証結果は、「false」とOR処理する必要があり、全体的な検証結果になります。
このキーワードは、サブスキーマを適用するときに正常に検証されたインデックスの配列であるアノテーション値を生成します。値は、サブスキーマがインスタンスのすべてのインデックスに適用されたときに正常に検証された場合、ブール値「true」になる場合があります。このキーワードのスキーマが適用されるインスタンス配列が空の場合、アノテーションが存在する必要があります。
"properties" の値はオブジェクトである必要があります。このオブジェクトの各値は、有効な JSON Schema である必要があります。
インスタンスとこのキーワードの値の両方に名前が表示される場合、その名前の子インスタンスが対応するスキーマに対して正常に検証された場合、検証は成功します。
このキーワードのアノテーション結果は、このキーワードによって一致したインスタンスプロパティ名のセットです。
このキーワードを省略すると、空のオブジェクトと同じアサーション動作になります。
「patternProperties」の値はオブジェクトでなければなりません。このオブジェクトの各プロパティ名は、ECMA-262 正規表現方言に従って、有効な正規表現であるべきです。このオブジェクトの各プロパティ値は、有効な JSON スキーマでなければなりません。
このキーワードの値のプロパティ名として現れる正規表現に一致するインスタンス名ごとに、その名前の子インスタンスが、一致する正規表現に対応する各スキーマに対して正常に検証される場合、検証は成功します。
このキーワードのアノテーション結果は、このキーワードによって一致したインスタンスプロパティ名のセットです。
このキーワードを省略すると、空のオブジェクトと同じアサーション動作になります。
「additionalProperties」の値は、有効な JSON スキーマでなければなりません。
このキーワードの動作は、同じスキーマオブジェクト内での「properties」と「patternProperties」の存在と注釈結果に依存します。「additionalProperties」を使用した検証は、「properties」または「patternProperties」のいずれかの注釈結果に現れないインスタンス名の子の値にのみ適用されます。
このようなすべてのプロパティについて、子インスタンスが「additionalProperties」スキーマに対して検証に成功した場合、検証は成功します。
このキーワードの注釈結果は、このキーワードのサブスキーマによって検証されたインスタンスプロパティ名のセットです。
このキーワードを省略すると、空のスキーマと同じアサーション動作になります。
実装は、「properties」内の名前と「patternProperties」内のパターンをインスタンスプロパティセットに対して直接チェックするなど、同じ効果を生み出す別の方法でこのキーワードを実装または最適化することを選択できます。注釈コレクションをサポートしていない実装は、そうする必要があります。
「propertyNames」の値は、有効な JSON スキーマでなければなりません。
インスタンスがオブジェクトの場合、このキーワードは、インスタンス内のすべてのプロパティ名が提供されたスキーマに対して検証される場合に有効になります。スキーマがテストしているプロパティ名は常に文字列であることに注意してください。
このキーワードを省略すると、空のスキーマと同じ動作になります。
これらのキーワードの目的は、スキーマ作成者が、隣接するキーワードの動的スコープのサブスキーマに対して正常に評価されなかった配列項目またはオブジェクトプロパティにサブスキーマを適用できるようにすることです。
これらのインスタンス項目またはプロパティは、「anyOf」のブランチのアサーションが失敗した場合など、1つ以上の隣接するキーワードサブスキーマに対して評価に失敗している可能性があります。このような失敗した評価は、項目またはプロパティが評価されたかどうかの判断には影響しないとみなされます。成功した評価のみが考慮されます。
配列内の項目またはオブジェクトプロパティが「正常に評価」された場合、論理的には、期待されるオブジェクトまたは配列の表現に関して有効であるとみなされます。たとえば、サブスキーマが2〜4個の車輪が必要な車を表しており、「wheels」の値が6の場合、インスタンスオブジェクトは車として「評価」されず、「wheels」プロパティは「未評価(既知のものとして正常に)」とみなされ、注釈は保持されません。
隣接するキーワードは同じスキーマオブジェクト内のキーワードであり、動的スコープのサブスキーマには、レキシカルサブスキーマだけでなく参照ターゲットも含まれることを思い出してください。
これらのキーワードの動作は、検証されるインスタンスの場所に適用される隣接キーワードの注釈結果に依存します。
「$vocabulary」を使用しないメタスキーマは、その URI が true の値で存在するかのように、この語彙を必須とみなす必要があります。
この語彙の現在のURIは、未評価アプリケータ語彙として知られており、<https://json-schema.dokyumento.jp/draft/2020-12/vocab/unevaluated>です。
対応するメタスキーマの現在のURIは、<https://json-schema.dokyumento.jp/draft/2020-12/meta/unevaluated>です。
エラーを修正するために、仕様のドラフト間で更新された語彙およびメタスキーマURIが公開される場合があります。実装では、この仕様のドラフト以降、次の仕様のドラフトより前の日付のURIは、ここにリストされているものと同じ構文とセマンティクスを示すと見なす必要があります。
スキーマキーワードは通常、互いの結果に影響を与えることなく独立して動作します。ただし、この語彙のキーワードは注目すべき例外です。
「unevaluatedItems」の値は、有効な JSON スキーマでなければなりません。
このキーワードの動作は、検証されるインスタンスの場所に適用される隣接キーワードの注釈結果に依存します。具体的には、「prefixItems」、「items」、および「contains」からの注釈で、これらのキーワードが「unevaluatedItems」キーワードに隣接している場合に来ます。これらの3つの注釈と「unevaluatedItems」は、隣接するすべてのインプレースアプリケータキーワードからも生成される可能性があります。これには、このドキュメントで定義されているインプレースアプリケータが含まれますが、これらに限定されません。
関連する注釈が存在しない場合、「unevaluatedItems」サブスキーマは配列内のすべての場所に適用する必要があります。関連する注釈のいずれかからブール値のtrue値が存在する場合、「unevaluatedItems」は無視する必要があります。それ以外の場合、サブスキーマは、「contains」の注釈値に現れない「prefixItems」の最大注釈値よりも大きいインデックスに適用する必要があります。
これは、「prefixItems」、「items」、「contains」、およびすべてのインプレースアプリケータを、このキーワードを評価する前に評価する必要があることを意味します。拡張キーワードの作成者は、このキーワードの後に評価する必要のあるインプレースアプリケータを定義しないでください。
「unevaluatedItems」サブスキーマがインスタンス配列内の任意の位置に適用される場合、「items」の動作と同様に、ブール値trueの注釈結果が生成されます。
このキーワードを省略すると、空のスキーマと同じアサーション動作になります。
「unevaluatedProperties」の値は、有効な JSON スキーマでなければなりません。
このキーワードの動作は、検証されるインスタンスの場所に適用される隣接キーワードの注釈結果に依存します。具体的には、「properties」、「patternProperties」、および「additionalProperties」からの注釈で、これらのキーワードが「unevaluatedProperties」キーワードに隣接している場合に来ます。これらの3つの注釈と「unevaluatedProperties」は、隣接するすべてのインプレースアプリケータキーワードからも生成される可能性があります。これには、このドキュメントで定義されているインプレースアプリケータが含まれますが、これらに限定されません。
「unevaluatedProperties」を使用した検証は、検証されるインスタンスの場所に適用される「properties」、「patternProperties」、「additionalProperties」、または「unevaluatedProperties」の注釈結果に現れないインスタンス名の子の値にのみ適用されます。
このようなすべてのプロパティについて、子インスタンスが「unevaluatedProperties」スキーマに対して検証に成功した場合、検証は成功します。
これは、「properties」、「patternProperties」、「additionalProperties」、およびすべてのインプレースアプリケータを、このキーワードを評価する前に評価する必要があることを意味します。拡張キーワードの作成者は、このキーワードの後に評価する必要のあるインプレースアプリケータを定義しないでください。
このキーワードの注釈結果は、このキーワードのサブスキーマによって検証されたインスタンスプロパティ名のセットです。
このキーワードを省略すると、空のスキーマと同じアサーション動作になります。
JSONスキーマはプラットフォームに依存しないように定義されています。そのため、プラットフォーム間の互換性を高めるために、実装は標準の検証出力形式に準拠する必要があります。このセクションでは、コンシューマーが検証結果を適切に解釈するために必要な最小要件について説明します。
JSONスキーマ出力は、セクション4.2.1で説明されているJSONスキーマデータインスタンスモデルを使用して定義されています。実装は、特定の言語やプラットフォームでサポートされている範囲で、これと異なる場合がありますが、シリアル化などの手段を介して、ここで定義されているJSON形式に変換できることが推奨されます。
この仕様では、4つの出力形式を定義しています。各形式の要件については、「出力構造」セクションを参照してください。
実装は、「flag」、「basic」、または「detailed」形式の少なくとも1つを提供する必要があり、「verbose」形式を提供できます。 「detailed」または「verbose」形式の1つ以上を提供する場合、「flag」形式も提供する必要があります。実装では、サポートする形式をドキュメントで指定する必要があります。
単純な「フラグ」出力に加えて、スキーマまたはインスタンスのデバッグに役立つ追加情報が役立ちます。各サブ結果には、このセクションに含まれる情報を少なくとも含む必要があります。
これらのコンポーネントをすべて含む単一のオブジェクトが出力ユニットと見なされます。
実装は、追加情報を提供することを選択できます。
検証パスに従う検証キーワードの相対位置。値はJSONポインタとして表現する必要があり、「$ref」や「$dynamicRef」などの参照によるアプリケータを含める必要があります。
#/properties/width/$ref/minimum
このポインタは、これらの参照によるアプリケータキーワードを含めるため、通常のJSONポインタプロセスで解決できない場合があることに注意してください。
この情報のJSONキーは「keywordLocation」です。
検証キーワードの絶対的な、参照解除された場所。値は、関連するスキーマオブジェクトの正規URIを使用して完全なURIとして表現する必要があり、「$ref」や「$dynamicRef」などの参照によるアプリケータを非終端パスコンポーネントとして含めてはなりません。エラーまたは注釈がそのキーワードに対するものである場合(解決不能な参照など)、そのようなキーワードで終わる可能性があります。[CREF12]ここで言う「絶対」とは、「絶対ファイルシステムパス」(完全な場所を意味する)の意味であり、RFC 3986からの「絶対URI」用語(スキーム付きだがフラグメントなしを意味する)ではありません。キーワードの絶対位置には、キーワードを識別するためにフラグメントが含まれます。
https://example.com/schemas/common#/$defs/count/minimum
この情報は、動的スコープが参照を通過しなかった場合、またはスキーマが絶対URIを「$id」として宣言していない場合にのみ省略できます。
この情報のJSONキーは「absoluteKeywordLocation」です。
検証中のインスタンス内のJSON値の位置。値はJSONポインタとして表現する必要があります。
この情報のJSONキーは「instanceLocation」です。
検証によって生成されるエラーまたは注釈。
エラーの場合、メッセージの具体的な表現は、この仕様では定義されていません。実装では、これを提供する必要があります。
注釈の場合、注釈を生成する各キーワードはその形式を指定します。デフォルトでは、キーワードの値です。
失敗した検証のJSONキーは「error」です。成功した検証の場合は「annotation」です。
2つの階層構造の場合、このプロパティにはネストされたエラーと注釈が保持されます。
失敗した検証でのネストされた結果のJSONキーは「errors」です。成功した検証の場合は「annotations」です。ネストされた結果を持つキーワードには、ローカルエラーまたは注釈も含まれる可能性があるため、複数形に注意してください。
出力は、「valid」という名前のブール値プロパティを含むオブジェクトである必要があります。結果に関する追加情報が必要な場合、出力には以下で説明するように「errors」または「annotations」も含まれている必要があります。
これらの例では、次のスキーマとインスタンスが使用されます。
{ "$id": "https://example.com/polygon", "$schema": "https://json-schema.dokyumento.jp/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」キーワードに5つのサブスキーマが含まれていて、2番目のサブスキーマが合格した場合、他の3つをチェックする必要はありません。ロジックは単に成功で返せばよいのです。
「基本」構造は、出力ユニットのフラットなリストです。
{ "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" } ] }
「詳細」構造はスキーマに基づいており、人間と機械の両方にとってより読みやすくなります。このように構造化することで、エラー間の関連性がより明確になります。たとえば、「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" } ] }
「詳細」構造は、スキーマと正確に一致する完全に実現された階層です。この構造は、エラーの場所が重要なフォームの生成や検証に適用されます。
これと「詳細」構造の主な違いは、すべての結果が返されることです。これには、削除される可能性のあるサブスキーマの検証結果(たとえば、失敗した検証のアノテーション、`not`キーワード内の成功した検証など)が含まれます。このため、各ノードにそのノードの検証結果を示す `valid` プロパティも持たせることが推奨されます。
この出力構造は非常に大きくなる可能性があるため、簡潔にするために、ここでは小さな例を示します。上記の例の完全な出力構造のURIは、<https://json-schema.dokyumento.jp/draft/2020-12/output/verbose-example>です。
// schema { "$id": "https://example.com/polygon", "$schema": "https://json-schema.dokyumento.jp/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 Schema は実装によって生成された出力を検証するために提供されています。そのURIは、<https://json-schema.dokyumento.jp/draft/2020-12/output/schema>です。
スキーマとインスタンスはどちらも JSON 値です。したがって、RFC 8259 で定義されているすべてのセキュリティに関する考慮事項が適用されます。
インスタンスとスキーマはどちらも、信頼できない第三者によって作成され、公共のインターネットサーバーにデプロイされることがよくあります。バリデーターは、スキーマに対する解析と検証が過剰なシステムリソースを消費しないように注意する必要があります。バリデーターは無限ループに陥ってはなりません。
悪意のある者が、非常に大きな値のコピーをアノテーションとして繰り返し収集させ、実装に過剰なシステムリソースを消費させる可能性があります。実装は、このようなシナリオでの過剰なシステムリソースの消費に対して保護する必要があります。
サーバーは、悪意のある者が既存の「$id」または非常に類似した「$id」を持つスキーマをアップロードすることにより、既存のスキーマの機能を変更できないようにする必要があります。
個々の JSON Schema ボキャブラリーには、独自のセキュリティに関する考慮事項もあります。詳細については、それぞれの仕様を参照してください。
スキーマの作成者は、「$comment」の内容に注意する必要があります。悪意のある実装は、仕様に違反してエンドユーザーに表示したり、予期される場合に削除に失敗したりする可能性があるためです。
悪意のあるスキーマ作成者は、実行可能なコードやその他の危険な素材を「$comment」内に配置する可能性があります。実装は、「$comment」の内容に基づいて解析したり、アクションを実行したりしてはなりません。
JSON Schemaの提案されたMIMEメディアタイプは、次のように定義されます。
JSON Schema固有のメディアタイプを必要とするJSON Schemaインスタンスの提案されたMIMEメディアタイプは、次のように定義されます。
[ecma262] | "ECMA-262, 第11版仕様", 2020年6月。 |
[RFC2119] | Bradner, S., "RFCにおける要件レベルを示すためのキーワード", BCP 14, RFC 2119, DOI 10.17487/RFC2119, 1997年3月。 |
[RFC3986] | Berners-Lee, T., Fielding, R. and L. Masinter, "Uniform Resource Identifier (URI): 一般的な構文", STD 66, RFC 3986, DOI 10.17487/RFC3986, 2005年1月。 |
[RFC6839] | Hansen, T. and A. Melnikov, "追加のメディアタイプ構造化構文サフィックス", RFC 6839, DOI 10.17487/RFC6839, 2013年1月。 |
[RFC6901] | Bryan, P., Zyp, K. and M. Nottingham, "JavaScript Object Notation (JSON) ポインター", RFC 6901, DOI 10.17487/RFC6901, 2013年4月。 |
[RFC8259] | Bray, T., "JavaScript Object Notation (JSON) データ交換形式", STD 90, RFC 8259, DOI 10.17487/RFC8259, 2017年12月。 |
[W3C.REC-ldp-20150226] | Speicher, S., Arwe, J. and A. Malhotra, "Linked Data Platform 1.0", World Wide Web Consortium Recommendation REC-ldp-20150226, 2015年2月。 |
[json-hyper-schema] | Andrews, H. and A. Wright, "JSON ハイパースキーマ:JSONのハイパーメディアアノテーションのためのボキャブラリー", Internet-Draft draft-handrews-json-schema-hyperschema-02, 2017年11月。 |
[json-schema-validation] | Wright, A., Andrews, H. and B. Hutton, "JSON Schema 検証:JSONの構造検証のためのボキャブラリー", Internet-Draft draft-bhutton-json-schema-validation-00, 2020年12月。 |
[RFC6596] | Ohye, M. and J. Kupke, "正規のリンク関係", RFC 6596, DOI 10.17487/RFC6596, 2012年4月。 |
[RFC7049] | Bormann, C. and P. Hoffman, "簡潔なバイナリーオブジェクト表現 (CBOR)", RFC 7049, DOI 10.17487/RFC7049, 2013年10月。 |
[RFC7231] | Fielding, R. and J. Reschke, "ハイパーテキスト転送プロトコル (HTTP/1.1): セマンティクスとコンテンツ", 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., "フラグメント識別子とメディアタイプ定義のベストプラクティス", World Wide Web Consortium WD WD-fragid-best-practices-20121025, 2012年10月。 |
[xml-names] | Bray, T., Hollander, D., Layman, A. and R. Tobin, "XML 1.1 における名前空間 (第2版)", 2006年8月。 |
以下のスキーマについて考えてみましょう。これは、「$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 および 9.2.1 に従って、リストされた任意の URI で識別できます。
参照 ("$ref") がどのように、どこに現れるかに基づいて、スキーマドキュメントを再配置するために、さまざまなツールが作成されています。この付録では、この仕様に準拠したユースケースとアクションについて説明します。
一緒に使用することを目的とした一連のスキーマリソースは、それぞれ独自のスキーマドキュメント、すべて同じスキーマドキュメント、またはその間の任意のドキュメントグループ化の粒度で編成できます。
さまざまな種類の参照削除を実行する多数のツールが存在します。この一般的なケースは、すべての参照がそのファイル内で解決できる単一のファイルを生成することです。これは通常、配布を簡素化するため、またはJSON Schemaライブラリのさまざまな呼び出しが多数のリソースを追跡してロードする必要がないように、コーディングを簡素化するために行われます。
この変換は、すべての静的参照 (たとえば、「$ref」) が正規 URI に解決される URI 参照を使用し、すべてのスキーマリソースのルートスキーマに絶対 URI が「$id」として指定されている限り、安全かつ可逆的に実行できます。
これらの条件が満たされると、各外部リソースは、リソースのスキーマオブジェクト間の参照を壊すことなく、また検証やアノテーションの結果を変化させることなく、"$defs"の下にコピーすることができます。"$defs"の下のスキーマの名前は、埋め込まれたリソースの正規URIには現れないため、それぞれが一意であれば動作に影響を与えません。
すべての参照を削除して単一のスキーマドキュメントを生成しようとしても、すべての場合において、元の形式と同一の動作をするスキーマが生成されるとは限りません。
"$ref"は他のキーワードと同様に扱われるようになり、同じスキーマオブジェクトに他のキーワードも許可されるため、すべての場合において非再帰的な"$ref"の削除を完全にサポートするには、比較的複雑なスキーマ操作が必要になる場合があります。安全な"$ref"削除変換のセットを決定したり提供したりすることは、この仕様の範囲外です。なぜなら、それらはスキーマ構造だけでなく、意図された使用法にも依存するからです。
以下に、単純な再帰的なツリー構造を記述する2つのスキーマを考えます。ツリーの各ノードは任意の型の "data" フィールドを持つことができます。最初のスキーマは、他のインスタンスプロパティを許可し、無視します。2番目のスキーマはより厳密で、"data" プロパティと "children" プロパティのみを許可します。"data" が "daat" と綴りを間違えたインスタンスの例も示します。
// tree schema, extensible { "$schema": "https://json-schema.dokyumento.jp/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.dokyumento.jp/draft/2020-12/schema", "$id": "https://example.com/strict-tree", "$dynamicAnchor": "node", "$ref": "tree", "unevaluatedProperties": false } // instance with misspelled field { "children": [ { "daat": 1 } ] }
これらの2つのスキーマをロードすると、それぞれに "$dynamicAnchor" という名前の "node" が存在することに気付くでしょう(これは単なる名前であり、"#" がないことに注意してください)。これにより、以下の完全なスキーマURIが得られます。
さらに、JSON Schemaの実装は、これらのフラグメントが "$dynamicAnchor" で作成されたという事実を追跡します。
インスタンスに "strict-tree" スキーマを適用すると、"$ref" で "tree" スキーマに移動し、その "children" サブスキーマを調べ、その "items" サブスキーマに "#node" への "$dynamicRef" があることを見つけます(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" を適用するのではなく、"strict-tree" のルートに再帰し、インスタンスの子に "tree" を適用します。
この例では、各スキーマの同じ場所、具体的にはリソースルートスキーマに両方の "$dynamicAnchor" があることを示しています。プレーンな名前フラグメントはJSON構造に依存しないため、ノードスキーマオブジェクトの1つまたは両方が "$defs" の下に移動されたとしても、これは同様に機能します。動的な参照を解決する方法を教えてくれるのは、JSON構造内の相関関係ではなく、一致する "$dynamicAnchor" の値です。
ボキャブラリーの作成者は、ボキャブラリーが広く使用されることを意図しており、他のボキャブラリーと組み合わされる可能性がある場合は、キーワード名の衝突を避けるように注意する必要があります。JSON Schemaは、正式な名前空間システムを提供しませんが、キーワード名を制限することもなく、任意の数の名前空間アプローチを可能にします。
ボキャブラリーは、別のボキャブラリーのキーワードの動作に関してキーワードの動作を定義したり、別のボキャブラリーのキーワードを制限または拡張された許容値セットで使用したりするなどして、互いに構築できます。このようなボキャブラリーの再利用がすべて、構築元のボキャブラリーと互換性のある新しいボキャブラリーになるわけではありません。ボキャブラリーの作成者は、期待される互換性のレベル(もしあれば)を明確に文書化する必要があります。
メタスキーマの作成者は、同じキーワードに対して矛盾する構文またはセマンティクスを定義する複数のボキャブラリーを組み合わせるために "$vocabulary" を使用しないでください。セマンティックの競合は通常、スキーマ検証では検出できないため、実装でそのような競合を検出することは期待されていません。競合するボキャブラリーが宣言された場合、結果として生じる動作は未定義です。
ボキャブラリーの作成者は、ボキャブラリーのキーワードの期待される使用法をそれ自体で検証するメタスキーマを提供する必要があります(SHOULD)。このようなメタスキーマは、追加のキーワードを禁止するべきではなく(SHOULD NOT)、コアボキャブラリーのキーワードを禁止してはなりません(MUST NOT)。
メタスキーマの作成者は、"allOf" キーワードを使用して、各ボキャブラリーのメタスキーマを参照することをお勧めしますが、特定のユースケースには、メタスキーマを構築するための他のメカニズムが適切な場合があります。
メタスキーマの再帰的な性質により、"$dynamicAnchor" キーワードと "$dynamicRef" キーワードは、既存のメタスキーマを拡張するのに特に役立ちます。これは、検証メタスキーマを拡張するJSONハイパースキーマメタスキーマで見ることができます。
メタスキーマは、宣言されたボキャブラリーに関連付けられたメタスキーマが記述する内容を超えて、ボキャブラリーに存在しないキーワードを記述するなど、追加の制約を課す場合があります。これにより、使用法をボキャブラリーのサブセットに制限したり、再利用を意図しないローカルで定義されたキーワードを検証したりできます。
ただし、メタスキーマは、ボキャブラリーが期待するJSON型とは異なるJSON型を要求するなど、宣言するボキャブラリーに矛盾してはなりません。結果として生じる動作は未定義です。
任意の環境でのボキャブラリーサポートをテストする必要がなく、ローカルで使用することを意図したメタスキーマは、"$vocabulary" を完全に省略しても安全です。
このメタスキーマは、コアボキャブラリーとアプリケーターボキャブラリーの両方を、拡張ボキャブラリーとともに明示的に宣言し、それらのメタスキーマを "allOf" で結合します。そのボキャブラリーのキーワードのみを記述する拡張ボキャブラリーのメタスキーマは、メインの例のメタスキーマの後に示されています。
メインの例のメタスキーマは、特に実装が複雑な "unevaluated" でプレフィックスされたキーワードを禁止することにより、未評価ボキャブラリーの使用法を制限します。これは、他のボキャブラリーで定義されたセマンティクスまたはキーワードセットを変更するものではありません。これは、"unevaluated" でプレフィックスされたキーワードを使用しようとするこのメタスキーマを使用するスキーマが、このメタスキーマに対する検証に失敗することを保証するだけです。
最後に、このメタスキーマは、どのボキャブラリーにも属していないキーワード "localKeyword" の構文を記述します。おそらく、このメタスキーマの実装者とユーザーは、"localKeyword" のセマンティクスを理解するでしょう。JSON Schemaは、ボキャブラリー外でキーワードセマンティクスを表現するメカニズムを定義していないため、それらが理解されている特定の環境以外での使用には適していません。
このメタスキーマは、一般的な用途のためにいくつかのボキャブラリーを組み合わせています。
{ "$schema": "https://json-schema.dokyumento.jp/draft/2020-12/schema", "$id": "https://example.com/meta/general-use-example", "$dynamicAnchor": "meta", "$vocabulary": { "https://json-schema.dokyumento.jp/draft/2020-12/vocab/core": true, "https://json-schema.dokyumento.jp/draft/2020-12/vocab/applicator": true, "https://json-schema.dokyumento.jp/draft/2020-12/vocab/validation": true, "https://example.com/vocab/example-vocab": true }, "allOf": [ {"$ref": "https://json-schema.dokyumento.jp/draft/2020-12/meta/core"}, {"$ref": "https://json-schema.dokyumento.jp/draft/2020-12/meta/applicator"}, {"$ref": "https://json-schema.dokyumento.jp/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.dokyumento.jp/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" で参照される単一ボキャブラリーの各メタスキーマが対応するボキャブラリーを宣言している場合でも、この新しいメタスキーマはそれらを再宣言する必要があります。
コアおよび検証仕様で定義されたすべてのボキャブラリーを組み合わせる標準メタスキーマ、およびこれらの仕様とハイパースキーマ仕様で定義されたすべてのボキャブラリーを組み合わせる標準メタスキーマは、追加の複雑な組み合わせを示しています。これらのメタスキーマのURIは、それぞれ検証仕様およびハイパースキーマ仕様にあります。
汎用メタスキーマは "minDate" の構文を検証できますが、"minDate" のセマンティックな意味の背後にあるロジックを定義するのはボキャブラリーです。(この例では、インスタンスの値が、スキーマのキーワードの値として指定された日付以降の日付である必要があるということです)。セマンティクス(この例では、インスタンスの値は、スキーマのキーワードの値として指定された日付以降の日付である必要がある)の理解がなければ、実装は構文的な使用法しか検証できません。この場合、これは日付形式の文字列であることを検証することを意味します(検証仕様で説明されているように、"format" が純粋にアノテーションとして機能する場合でも検証されるように "pattern" を使用します)。
参照の存在は、検証結果に対して透過的であることが期待されますが、コードジェネレーターや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" プロパティはそうではありません。これは、別のクラスのインスタンスではなく、サブフィールドを持つ単なるフィールドです。
このスタイルの使用法では、アノテーションが参照と同じオブジェクト内にある必要があり、参照として認識できる必要があります。
JSON Schemaの初期ドラフトを作成した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に感謝します。
[CREF13]このセクションは、インターネットドラフトの状態を離れる前に削除されます。