インターネット技術特別調査委員会 H.アンドリュース、編
インターネットドラフト
意図されたステータス: 情報提供 A.ライト、編
有効期限: 2020年3月20日 2019年9月17日

JSONハイパースキーマ: JSONのハイパーメディアアノテーションのための語彙
draft-handrews-json-schema-hyperschema-02

概要

JSONスキーマは、さまざまな語彙を使用してJSONデータを記述するためのJSONベースの形式です。このドキュメントでは、JSONドキュメントにハイパーリンクをアノテーションするための語彙を指定します。これらのハイパーリンクには、HTTPなどのハイパーメディア環境を介してリモートリソースを操作および操作する方法、およびインスタンスの値に基づいてリンクが使用可能かどうかを記述する属性が含まれます。このドキュメントで説明されているハイパーリンクのシリアル化形式は、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 TrustのIETFドキュメントに関する法的規定(https://trustee.ietf.org/license-info)に従います。これらのドキュメントには、このドキュメントに関するあなたの権利と制限が記載されているため、注意深く確認してください。このドキュメントから抽出されたコードコンポーネントには、Trust Legal Provisionsのセクション4.eに記載されている簡略化されたBSDライセンステキストを含める必要があり、簡略化されたBSDライセンスに記載されているように保証なしで提供されます。


目次

1. はじめに

JSONハイパースキーマは、HTTPなどのハイパーメディア環境を介してリモートJSONリソースを処理および操作するためのハイパーリンクと指示でJSONドキュメントにアノテーションを付けるためのJSONスキーマの語彙です。

JSONハイパースキーマという用語は、これらのキーワードを使用するJSONスキーマを指すために使用されます。 「ハイパースキーマ」という用語自体は、この仕様の範囲内のJSONハイパースキーマを指します。

リンクを指定するために導入された主要なメカニズムは、リンク記述オブジェクト(LDO)です。これは、RFC 8288、セクション2で定義されている抽象リンクモデルのシリアル化です。

この仕様では、JSONスキーマコアおよびJSONスキーマ検証仕様で定義されている概念、構文、および用語を使用します。読者はこれらの仕様のコピーを持っていることが推奨されます。

2. 表記上の規約

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

3. 概要

JSONハイパースキーマを使用すると、インスタンスデータからハイパーリンクを構築する方法を記述することにより、JSONドキュメントからハイパーメディアシステムを構築できます。

JSONインスタンスドキュメントと、そのインスタンスに有効なapplication/schema+jsonハイパースキーマの組み合わせは、単一のハイパーメディア表現として動作します。この分離を許可することにより、ハイパースキーマベースのシステムは、プレーンJSONを予期するアプリケーションを適切にサポートしながら、ハイパースキーマ対応のアプリケーションとユーザーエージェントに完全なハイパーメディア機能を提供できます。

ユーザーエージェントは、application/schema+jsonメディアタイプと、ハイパースキーマ語彙の存在を示す「$schema」値を検索することにより、ハイパースキーマの存在を検出できます。その後、ユーザーエージェントはJSONハイパースキーマの実装を使用して、スキーマとインスタンスドキュメントの組み合わせへのインターフェースを、単一ドキュメントハイパーメディア表現形式と同様に、リソースの単一の論理表現として提供できます。

ハイパースキーマを使用すると、転送中のバイト数を減らすことができ、リンク構築の負担をサーバーから各クライアントに分散できます。クライアントアプリケーションがそのリンクを要求しない限り、ユーザーエージェントはリンクを構築する必要はありません。 JSONハイパースキーマは、サーバー側で使用して、他のリンクのシリアル化または表現形式を実行時に生成したり、サーバープッシュの使用を促進するために事前にリンクをたどったりすることもできます。

以下は、IANA登録済みのリンクリレーションタイプ「self」を使用して、単一のリンクを追加するハイパースキーマの例です。これは、「id」という名前の既知のオブジェクトフィールドが1つあるインスタンスから構築されます。

{
    "type": "object",
    "properties": {
        "id": {
            "type": "number",
            "readOnly": true
        }
    },
    "links": [
        {
            "rel": "self",
            "href": "thing/{id}"
        }
    ]
}
                

インスタンスが{ "id": 1234}であり、RFC 3986セクション5.1によるベースURIが「https://example.com/api/」である場合、「https://example.com/api/thing/1234」が結果のリンクのターゲットURIです。

3.1. 用語

「スキーマ」、「インスタンス」、「メタスキーマ」という用語は、JSONスキーマコア仕様で定義されているように解釈されます。

「適用可能」および「添付」という用語は、JSONスキーマコア仕様のセクション3.1で定義されているように解釈されます。

「リンク」、「リンクコンテキスト」(または「コンテキスト」)、「リンクターゲット」(または「ターゲット」)、および「ターゲット属性」という用語は、RFC 8288のセクション2で定義されているように解釈されます。

「ユーザーエージェント」という用語は、RFC 7230のセクション2.1で定義されているように解釈されます。これは、特にHTTPクライアントではなく、ハイパーメディアシステムで使用される可能性のある任意のプロトコルに適用されるように一般化されています。

この仕様では、次の用語を定義します。

JSONハイパースキーマ
この仕様で定義されたキーワードを使用するJSONスキーマ。
ハイパースキーマ
このドキュメント内では、「ハイパースキーマ」という用語は常にJSONハイパースキーマを指します。
リンクの有効性
インスタンスの有効なリンクは、そのインスタンスに適用可能であり、リンク記述オブジェクトのキーワードによって課せられた要件に失敗しないリンクです。無効なリンクは、「if」や「oneOf」(コア仕様から)などのキーワードを使用して、表現の構造または値に条件付きのリンクを記述する場合に発生する可能性があることに注意してください。
汎用ユーザーエージェント
サポートされている標準化されたリンクリレーション、メディアタイプ、URIスキーム、およびプロトコルの中から、任意のサーバーの任意のリソースと対話するために使用できるユーザーエージェント。ただし、メディアタイプの特定のプロファイルを特別に処理するように拡張できる場合があります。
クライアントアプリケーション
特定の目的でハイパーメディアシステムを使用するアプリケーション。このようなアプリケーションは、独自のユーザーエージェントである場合もあれば、汎用ユーザーエージェントの上に構築されている場合もあります。クライアントアプリケーションは、アプリケーションのドメインに固有のリンクリレーション、メディアタイプ、URIスキーム、プロトコル、およびデータ構造に関する知識を使用してプログラミングされます。
クライアント入力
ユーザーエージェントを介して、そして最も多くの場合、クライアントアプリケーションを介して提供されるデータ。このようなデータは、ユーザーから対話形式で要求したり、コマンドライン引数、構成ファイル、またはソースコードにハードコードされた値などの形式で対話前に提供したりできます。
操作
ネットワークリクエスト(プロトコルを示す「http://」などのスキームを持つURIの場合)などのハイパーリンクの特定の用途、またはリンクに基づいてアクションを起こすこと(「data:」URIからのデータの読み取り、または「mailto:」リンクに基づく電子メールメッセージの構築)。複数のメソッドをサポートするHTTPなどのプロトコルの場合、各メソッドは同じリンクに対する個別の操作と見なされます。

3.2. 機能

JSON Hyper-Schemaの実装は、ハイパースキーマ、インスタンス、場合によってはクライアント入力を受け取り、完全に解決された有効なリンクのセットを生成できます。RFC 8288、セクション2で定義されているように、リンクはコンテキスト、型付き関係、ターゲット、およびオプションで追加のターゲット属性で構成されます。

関係タイプとターゲット属性は、各リンクのリンク記述オブジェクトから直接取得されます。コンテキストとターゲット識別子は、URIテンプレート、インスタンスデータ、(ターゲット識別子の場合)クライアント入力のいくつかの組み合わせから構築されます。

ターゲットは常にURIによって完全に識別されます。application/jsonやJSON Hyper-Schemaで使用できる他の多くのメディアタイプにはURIフラグメント識別子の構文がないため、コンテキストはURIによって部分的にのみ識別される場合があります。このような場合、残りの識別はJSONポインタとして提供されます。

いくつかのIANA登録済みのリンクリレーションタイプは、JSON Hyper-Schemaドキュメントで特定のセマンティクスを与えられています。「self」リンクは、インスタンスドキュメントが表すリソースと対話するために使用されますが、「collection」および「item」リンクは、コレクション固有のセマンティクスを想定できるリソースを識別します。

4. メタスキーマと出力スキーマ

JSON Hyper-Schemaメタスキーマの現在のURIは、<https://json-schema.dokyumento.jp/draft/2019-09/hyper-schema#>です。

この語彙(ハイパースキーマ語彙として知られています)の現在のURIは、<https://json-schema.dokyumento.jp/draft/2019-09/vocab/hyper-schema>です。

対応するメタスキーマの現在のURIは、ハイパースキーマキーワード(「base」と「link」)のみを記述するという点で、上記の便宜的なメタスキーマとは異なります。<https://json-schema.dokyumento.jp/draft/2019-09/meta/hyper-schema>です。

リンク記述形式はJSON Schemaなしで使用でき、この形式の使用は、リンクを使用するデータ構造のスキーマとして、規範的なリンク記述スキーマを参照することで宣言できます。規範的なリンク記述スキーマのURIは、<https://json-schema.dokyumento.jp/draft/2019-09/links#>です。

JSON Hyper-Schemaの実装は、任意の形式で出力できます。ただし、適合性テストスイートで使用するために特定の形式が定義されており、これは「実装要件」のポイントを説明し、によって生成された出力を示すためにも使用されます。実装では、テストを容易にするためにこの形式で出力できることが推奨されます。推奨される出力形式を記述するJSON SchemaのURIは、<https://json-schema.dokyumento.jp/draft/2019-09/output/hyper-schema#>です。

エラーを修正するために、仕様ドラフト間で更新された語彙およびメタスキーマのURIが公開される場合があります。実装では、この仕様ドラフト以降で次の仕様ドラフトより前の日付のURIは、ここにリストされている構文とセマンティクスと同じものを示すとみなすべきです。

5. スキーマキーワード

JSON Schemaコアのセクション3.1で定義されているように、インスタンス内の位置に適用可能なすべてのスキーマからのハイパースキーマキーワードは、そのインスタンスで使用できます。

複数のサブスキーマが特定のサブインスタンスに適用可能な場合、すべての「link」配列は、任意の順序で、単一のセットに結合する必要があります。結果として得られるセット内の各オブジェクトは、同じスキーマおよびすべての親スキーマからの、解決順序で適用可能な「base」値の独自のリストを保持する必要があります。

すべてのJSON Schemaキーワードと同様に、このセクションで説明するすべてのキーワードはオプションです。最小限の有効なJSON Hyper-schemaは、空のオブジェクトです。

5.1. base

存在する場合、このキーワードは最初にURIテンプレートとして解決する必要があり、次にインスタンスの現在のURIベースに対してURI参照として解決する必要があります。結果は、「base」を含むサブスキーマおよびその内部のすべてのサブスキーマを処理する間、インスタンスの新しいURIベースとして設定する必要があります。

「base」テンプレートを解決するプロセスは、「anchor」で使用するために解決される場合と、「href」で使用するために解決される場合とで異なる可能性があり、これはURIテンプレートのセクションで詳しく説明します。

5.2. links

スキーマの「links」プロパティは、リンク記述オブジェクトをインスタンスに関連付けるために使用されます。このプロパティの値は配列である必要があり、配列内の項目は、以下で定義するようにリンク記述オブジェクトである必要があります。

6. リンク記述オブジェクト

リンク記述オブジェクト(LDO)は、RFC 8288、セクション2で定義されている抽象リンクモデルのシリアル化です。そのドキュメントで説明されているように、リンクはコンテキスト、関係タイプ、ターゲット、およびオプションでターゲット属性で構成されます。JSON Hyper-SchemaのLDOは、これらすべてに加えて、さまざまな方法でリンクで使用する入力の説明にJSON Schemaを使用する追加機能を提供します。

リンクコンテキストとターゲットを識別するためにURIテンプレートを使用すること、およびターゲットを識別する際のオプションのクライアント入力のさらなる使用により、LDOは、JSONインスタンスドキュメントで使用した場合に複数のリンクに解決される可能性のあるリンクトップレートです。

LDOの特定の用途(通常、プロトコルを介したリクエストとレスポンスを含む)は、操作と呼ばれます。多くのプロトコルでは、任意のリンクで複数の操作が可能です。プロトコルは、ターゲットのURIスキームによって示されます。すべてのURIスキームが通信に使用できるプロトコルを示すわけではなく、そのようなプロトコルを示すURIスキームを持つリソースでさえ、そのプロトコルを介して利用できる必要はないことに注意してください。

リンク記述オブジェクトはオブジェクトである必要があり、「href」および「rel」プロパティが存在する必要があります。各キーワードは、このセクションで簡単に説明され、追加の使用説明と包括的な例が後でドキュメントで示されます。

6.1. リンクコンテキスト

JSON Hyper-Schemaでは、リンクのコンテキストリソースは、デフォルトで、(JSON Schemaコア仕様のセクション3.1で定義されているように)それがアタッチされているサブインスタンスです。これは多くの場合、インスタンスドキュメント全体ではありません。このデフォルトのコンテキストは、このセクションのキーワードを使用して変更できます。

インスタンスのメディアタイプによっては、正確なデフォルトのコンテキストリソースにURIを割り当てることが可能な場合と不可能な場合があります。特に、application/jsonはURIフラグメント解決構文を定義していないため、プレーンなJSONドキュメント内のプロパティまたは配列要素はURIによって完全に識別できません。完全なURIを生成できない場合は、コンテキストの位置を、インスタンスドキュメントのURIとともに、別のプレーン文字列のJSONポインタで伝達する必要があります。

実装は、リンクコンテキストのURIを構築できる必要があり、(完全な識別に必要な場合)RFC 6901、セクション5に従って、URIフラグメントの代わりに文字列表現形式のJSONポインタを構築できる必要があります。URIテンプレートに基づくURIを構築するプロセスは、URIテンプレートのセクションに記載されています。

6.1.1. anchor

このプロパティは、リンクのコンテキストURIを設定します。プロパティの値はURIテンプレートであり、結果のURI参照はインスタンスのベースURIに対して解決する必要があります。

URIは、「href」プロパティについて説明したのと同じプロセスを使用して、提供されたURIテンプレートから計算されます。ただし、「hrefSchema」は適用してはなりません。ターゲットURIとは異なり、コンテキストURIはユーザー入力を受け付けません。

6.1.2. anchorPointer

このプロパティは、リンクのコンテキストリソースと見なされるインスタンス内のポイントを変更します。プロパティの値は、JSON文字列形式の有効なJSONポインタ、またはデフォルトのコンテキストに対して評価される有効な相対JSONポインタである必要があります。

既知のURIを持つ代替コンテキストは、「anchor」キーワードを使用して設定するのが最適ですが、application/jsonのフラグメント識別子構文がないため、URIを使用してJSONインスタンス内のコンテキストを変更することは通常できません。

JSONポインタをフラグメント識別子構文として定義する「+ json」メディアタイプでも、デフォルトのコンテキストが配列内にネストされている場合、同じネストされたJSONオブジェクト内の別のプロパティへのポインタを構築するために、その配列内のデフォルトのコンテキストの位置のインデックスを取得することはできません。これは例で示されます。

このキーワードの処理結果は、インスタンスのメディアタイプがそのようなフラグメントを許可する場合はURIフラグメントである必要があります。それ以外の場合は、文字列でエンコードされたJSONポインタである必要があります。

6.2. リンクリレーションタイプ

リンクの関係タイプは、そのセマンティクスを識別します。これは、アプリケーションがリソースと対話する方法を伝える主な手段です。

関係定義は通常メディアタイプに依存せず、ユーザーは最も適切な既存の受け入れられた関係定義を利用することを推奨します。

6.2.1. rel

このプロパティの値は、文字列または文字列の配列のいずれかである必要があります。値が配列の場合は、少なくとも1つの文字列を含む必要があります。

各文字列は、RFC 8288、セクション2.1で定義されているように、単一のリンクリレーションタイプである必要があります。これには、別のリンクリレーションタイプの存在または不在に基づいて追加のセマンティクスを推論すべきではないという制限が含まれます。

このプロパティは必須です。

6.2.2. 「self」リンク

RFC 4287のセクション4.2.7.2で最初に定義された「self」リンクは、ターゲットURIがリンクコンテキストと同等のリソースを識別することを示します。JSON Hyper-Schemaでは、「self」リンクはインスタンスから解決可能である必要があり、したがって「hrefSchema」は存在してはなりません。

ハイパースキーマの作成者は、「self」リンクに必要なすべてのインスタンスデータがあることを確認するために「templateRequired」を使用する必要があります。

ハイパースキーマの実装は、現在のインスタンスドキュメント全体をコンテキストとする関係タイプ「self」のリンクが、ユーザーエージェントがそのインスタンスドキュメントで表されるリソースと対話する方法を記述していることを認識する必要があります。

6.2.3. 「collection」および「item」リンク

RFC 6573は、「item」および「collection」リンクリレーションタイプを定義および登録します。JSON Hyper-Schemaは、これらのタイプで示されるコレクションリソースに追加のセマンティクスを課します。

実装は、「collection」リンクのターゲットと「item」リンクのコンテキストをコレクションとして認識する必要があります。

ハイパーメディアにおけるよく知られたデザインパターンは、コレクションリソースを使用してコレクションのメンバーを作成し、サーバーが割り当てた URI を付与することです。URI スキームが示すプロトコルが、サーバーが割り当てた URI を持つリソースを作成するのに適した特定の方法を定義している場合、これらのリンク関係タイプで識別されるコレクションリソースは、コレクションメンバーの作成のセマンティクスと競合するような、その方法のセマンティクスを定義してはなりません。コレクションリソースは、このようなプロトコルメソッドを介してアイテムの作成を実装することができ、ユーザーエージェントは、そのような操作が存在する場合、アイテム作成のセマンティクスを持つと仮定してもよいです。

このようなメソッドは、JSON ハイパースキーマのデータ送信の概念に対応するため、リンクの「submissionSchema」フィールドは、「item」リンクのターゲットリソース、または「collection」リンクのコンテキストリソースの「self」リンクで示される、コレクションのアイテムの表現のスキーマと互換性がある必要があります。

6.2.4. 拡張関係タイプを使用する

(「related」を除く)登録された関係が適用されない場合、RFC 8288 のセクション 2.1.2で説明されているように、ユーザーは独自の拡張関係タイプを作成することが推奨されます。リンク関係タイプ URI を選択する最も簡単な方法は、システムの主要なリソースを識別するためにすでに使用されている URI スキームを使用するか、RFC 4151 で定義されている「tag」などの人間が読める、非参照可能な URI スキームを使用することです。

拡張関係タイプ URI は、それを許可するスキームを使用している場合でも、参照可能である必要はありません。

6.3. リンクターゲット

ターゲット URI テンプレートは、インスタンスデータを利用して、リンクのターゲットを識別するために使用されます。さらに、「hrefSchema」を使用すると、このテンプレートは、クライアントの入力に基づいて使用できるターゲットリソースのセットを識別できます。クライアント入力の有無にかかわらず、URI テンプレートを解決する完全なプロセスについては、URI テンプレートのセクションで説明します。

6.3.1. href

「href」リンク記述プロパティの値は、関連リソースのターゲット URI を決定するために使用されるテンプレートです。インスタンスプロパティの値は、インスタンスのベース URI に対してURI 参照として解決される必要があります。

このプロパティは必須です。

6.4. URI テンプレートの解決の調整

このセクションのキーワードは、ハイパースキーマに関わるすべての URI テンプレート(「base」、「anchor」、および「href」)を解決するときに使用されます。テンプレート解決の完全なアルゴリズムについては、URI テンプレートのセクションを参照してください。

「base」テンプレートを解決する場合、解決が開始されるアタッチメントポイントは、「base」キーワード自体のアタッチメントポイントではなく、「base」テンプレートの解決を必要とする「href」または「anchor」キーワードのアタッチメントポイントであることに注意してください。

6.4.1. templatePointers

「templatePointers」リンク記述プロパティの値はオブジェクトでなければなりません。オブジェクト内の各プロパティ値は、有効なJSON ポインタ、またはテンプレートが解決されるリンクのアタッチメントポイントを基準に評価される有効な相対 JSON ポインタでなければなりません。

解決されるテンプレート内の変数名と一致するオブジェクト内の各プロパティ名について、そのプロパティの値は、その変数の変数解決の開始位置を調整します。解決されるテンプレート内のテンプレート変数名と一致しないプロパティは無視する必要があります。

6.4.2. templateRequired

このキーワードの値は配列でなければならず、要素は一意でなければなりません。各要素は、パーセントエンコーディングなしで、リンクの URI テンプレート内の変数と一致する必要があります。URI テンプレートの解決プロセス全体が完了した後、この配列に存在する変数が値を持たない場合、リンクは使用してはなりません。

6.5. リンクターゲット属性

このセクションのすべてのプロパティは、アドバイザリーのみです。「title」や「description」などのキーワードは主にリンクをユーザーに提示するために使用されますが、リンクのインタラクションまたは応答の性質を予測するキーワードは、信頼できるとは見なしてはなりません。ターゲットリソースのランタイム動作は、LDO のターゲット属性と競合する場合は常に尊重する必要があります。

6.5.1. title

このプロパティは、リンクのタイトルを定義します。値は文字列でなければなりません。

ユーザーエージェントは、リンクをユーザーに提示するときにこのタイトルを使用できます。

6.5.2. description

このプロパティは、タイトルに存在する以上の追加情報を提供します。値は文字列でなければなりません。タイトルは短い方が好ましいですが、説明はリンクの目的と使用法についてより詳細に説明するために使用できます。

ユーザーエージェントは、リンクをユーザーに提示するときにこの説明を使用できます。

6.5.3. targetMediaType

このプロパティの値は、このリソースをフェッチするときに返されることが期待されるメディアタイプRFC 2046を表します。このプロパティ値は、RFC 7231、セクション 5.3.2 - HTTP 「Accept」ヘッダーで定義されているのと同じパターンを使用して、メディア範囲にすることもできます。

このプロパティは、他のリンクシリアル化形式の「type」プロパティに類似しています。ユーザーエージェントは、リンクをたどる前にユーザーに提示するインターフェイスを通知するためにこの情報を使用できますが、結果のデータの解釈にこの情報を使用してはなりません。代わりに、ユーザーエージェントは、ランタイム解釈のために応答によって与えられたメディアタイプを使用する必要があります。「targetMediaType」の誤用の詳細な検討については、「セキュリティに関する懸念」のセクションを参照してください。

コンテンツネゴシエーションをサポートするプロトコルの場合、実装は、「headerSchema」でプロトコル固有の情報を使用して、可能なターゲットメディアタイプを記述することを選択できます。プロトコル固有の情報と「targetMediaType」の両方が存在する場合、「targetMediaType」の値はプロトコル固有の情報と互換性がある必要があり、コンテンツネゴシエーションがない場合に返されるメディアタイプを示す必要があります。

そのようなプロトコル固有の情報が利用できない場合、または実装が関係するプロトコルを認識しない場合、値は「application/json」であると見なされる必要があります。

6.5.4. targetSchema

このプロパティは、リンクターゲットの表現を記述することが期待されるスキーマを提供します。プロトコルによっては、スキーマは、リンクで実行された特定の操作に対するリクエストまたはレスポンスを記述する場合としない場合があります。このキーワードが HTTP でどのように使用されるかの詳細については、JSON ハイパースキーマと HTTP のセクションを参照してください。

6.5.5. targetHints

[CREF1]このセクションでは、その構造のほとんどを URI スキームで示されるプロトコルに委ねることにより、包括性と柔軟性のバランスを取ろうとしています。リソースは、参照可能なスキームを持つ URI で識別される可能性がありますが、そのプロトコルでアクセスできない可能性があることに注意してください。現在非常に緩いですが、このセクションはドラフトのフィードバックに基づいてより明確になることが期待されており、将来のドラフトで大幅に変更される可能性があります。

このプロパティの値は、アドバイザリーのみです。これは、通常は HTTP HEAD または OPTIONS リクエストへの応答で返されるヘッダーなどのプロトコル固有の制御情報またはメタデータの形式で、ターゲットリソースとの対話を通じて発見されることが期待される情報を表します。プロトコルは「href」URI スキームによって決定されますが、リソースがそのようなプロトコルでアクセス可能であるとは限りません。

このプロパティの値はオブジェクトである必要があります。このオブジェクトのキーは、制御データフィールド名の小文字形式である必要があります。複数値フィールドを均一に処理するために、各値は配列である必要があります。複数の値は、単一の文字列としてではなく、配列として提示する必要があります。

JSON オブジェクトとしての表現に適さない制御情報を持つプロトコルは、配列などの別のデータ型で表現できます。

示されたプロトコルの一部として理解できない値は、JSON ハイパースキーマの実装によって無視される必要があります。アプリケーションは、そのような値を利用してもよいですが、他の実装との相互運用性を想定してはなりません。

実装は、このオブジェクトですべての発見可能な情報が説明されていると想定してはなりません。クライアントアプリケーションは、このプロパティの値と矛盾するランタイム応答を適切に処理する必要があります。

クライアントアプリケーションは、実装がこのプロパティの値に基づいて自動的にアクションを実行すると想定してはなりません。

HTTP および同様のプロトコルでのこのキーワードの使用に関するガイダンスについては、「JSON ハイパースキーマと HTTP」を参照してください。

6.6. リンク入力

リンクでクライアント入力を使用する方法は 4 つあり、それぞれが個別のリンク記述オブジェクトキーワードによって処理されます。操作を実行する場合、ユーザーエージェントは、セマンティクスに関係のないスキーマを無視する必要があります。

6.6.1. hrefSchema

「hrefSchema」リンク記述プロパティの値は、有効な JSON スキーマでなければなりません。このスキーマは、「href」の URI テンプレートを入力するためのユーザー入力またはその他のユーザーエージェントデータを検証するために使用されます。

「hrefSchema」を省略するか、スキーマ全体を「false」に設定すると、ユーザーエージェントデータが受け入れられなくなります。

特定の変数に適用されるサブスキーマを JSON リテラル値「false」に設定すると、その単一の変数に対してユーザーエージェントデータが受け入れられなくなります。

インスタンスデータから解決できるテンプレート変数の場合、インスタンスデータが「hrefSchema」のすべての適用可能なサブスキーマに対して有効な場合、その変数の入力データセットを事前に入力するために使用する必要があります。

データがインスタンスから事前に入力された場合でも、「hrefSchema」内のその変数の検証スキーマは、インスタンスデータの場所に適用される検証スキーマと同一である必要がないことに注意してください。これにより、ユーザーエージェントデータに対して異なる検証ルール(日付と時刻の入力でスペルアウトされた月をサポートするなど)を可能にしますが、ストレージには標準の日付と時刻の形式を使用します。

入力が受け入れられた後、事前に入力されたインスタンスデータを上書きする可能性があり、結果のデータセットは「hrefSchema」の値に対して正常に検証される必要があります。そうでない場合、リンクは使用してはなりません。有効な場合、「URI テンプレート」セクションに示されているプロセスは、この更新されたデータセットで続行されます。

6.6.2. headerSchema

[CREF2]「targetHints」と同様に、このキーワードは柔軟性と明確さのバランスを取るために、実験とフィードバックを促進するためにやや不特定です。

存在する場合、このプロパティは、プロトコル固有のリクエストヘッダーまたは類似の制御およびメタデータのスキーマです。このオブジェクトの値は、有効な JSON スキーマでなければなりません。プロトコルは「href」URI スキームによって決定されますが、リソースがそのようなプロトコルでアクセス可能であるとは限りません。スキーマはアドバイザリーのみであり、ターゲットリソースの動作はその存在によって制約されません。

このキーワードの目的は、ターゲットリソースのインタラクション機能をアドバタイズし、ユーザーエージェントおよびクライアントアプリケーションに、どのようなヘッダーおよびヘッダー値が有用である可能性が高いかを示すことです。ユーザーエージェントおよびクライアントアプリケーションは、スキーマを使用して関連ヘッダーを検証してもよいですが、ヘッダーまたは値の欠落が使用を禁止されていると想定してはなりません。スキーマ作成者は「additionalProperties」を false に設定できますが、これは推奨されず、クライアントアプリケーションまたはユーザーエージェントがリクエスト時に追加のヘッダーを提供することを妨げてはなりません。

JSON データモデルからヘッダーへの正確なマッピングは、プロトコルに依存します。ただし、ほとんどの場合、このスキーマは「object」のタイプを指定する必要があり、プロパティ名は、制御データフィールド名の小文字形式である必要があります。「targetHints」と同様に、値は、1 つの値のみが予想される場合でも、複数の値を許可するために配列として記述する必要があります。

「JSON Hyper-Schema と HTTP」のセクションで、このキーワードを HTTP および類似のプロトコルで使用するための詳細なガイダンスを参照してください。

「headerSchema」は、プロトコルがサポートする任意のリクエストメソッドまたはコマンドに適用できます。リクエストを生成する際、ユーザーエージェントとクライアントアプリケーションは、そのリクエストに関係のないヘッダーのスキーマを無視する必要があります(SHOULD)。

6.6.3. ターゲットリソース表現の操作

JSON Hyper-Schema では、「targetSchema」は、ターゲットリソースの表現に関する非権威的な記述を提供します。クライアントアプリケーションは、「targetSchema」を使用して、表現を置き換えたり修正するための入力を構造化したり、パッチメディアタイプに基づいてパッチドキュメントを作成するためのベース表現として使用したりできます。

あるいは、「targetSchema」が存在しない場合や、クライアントアプリケーションが権威ある情報のみを使用することを好む場合は、ターゲットリソースと対話して、その表現構造を確認または発見することができます。

「targetSchema」は、レスポンスセマンティクスがターゲットリソースの表現であることを示す場合を除き、リンク操作のレスポンスを記述するためのものではありません。すべての場合において、レスポンス自体によって示されるスキーマが権威あるものです。詳細な例については、「JSON Hyper-Schema と HTTP」を参照してください。

6.6.4. 処理のためのデータ送信

「submissionSchema」および「submissionMediaType」キーワードは、ターゲットリソースによって実装される処理関数のドメインを記述します。それ以外の場合は、上記のとおり、送信スキーマとメディアタイプは、それらが関係のない操作では無視されます。

6.6.4.1. submissionMediaType

このプロパティが存在する場合、クライアントアプリケーションとユーザーエージェントが「submissionSchema」で記述されたリクエストペイロードに使用する必要があるメディアタイプ形式を示します。

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

「submissionMediaType」と「submissionSchema」は、HTTP URI に限定されないことに注意してください。[CREF3]この記述は、例が最終的に配置される場所に移動する可能性があります。

6.6.4.2. submissionSchema

このプロパティには、「submissionMediaType」プロパティに従ってエンコードされ、処理のためにターゲットリソースに送信されるドキュメントの許容可能な構造を定義するスキーマが含まれています。これは、ターゲットリソースによって実装される処理関数のドメインを記述するものと見なすことができます。

これは、「targetSchema」プロパティとは別の概念です。 「targetSchema」はターゲット情報リソース(PUTリクエストでリソースの内容を置き換える場合を含む)を記述するのに対し、「submissionSchema」はリソースによって評価されるユーザーが送信したリクエストデータを記述します。「submissionSchema」は、ターゲット表現の観点から必ずしも定義されていないペイロードを持つリクエストで使用することを目的としています。

「submissionSchema」を省略すると、「true」の値と同じ動作になります。

7. 実装要件

大まかに言うと、適合する実装は以下の要件を満たします。これらの各要件については、個々のキーワードセクションとキーワードグループの概要で詳しく説明します。

実装が「self」、「collection」、「item」リンクを認識する方法に関する要件は、リンク関係タイプセクションで完全に説明されており、ここでは繰り返しません。

実装にとって必須の形式ではありませんが、テストスイートで使用される出力形式は、各リンクを使用する前に計算する必要がある内容をまとめたものです。

contextUri
コンテキストリソースの完全に解決された URI(スキーム付き)。コンテキストがリソース全体ではなく、使用可能なフラグメント識別子構文がある場合は、URI にフラグメントが含まれます。`application/json` にはそのような構文がないことに注意してください。
contextPointer
コンテキストリソースのインスタンス内の場所の JSON ポインター。インスタンスメディアタイプがフラグメント識別子として JSON ポインターをサポートしている場合、このポインターは「contextUri」フィールドのフラグメントにエンコードされたポインターと同じになります。
rel
リンク関係タイプ。複数のリンク関係タイプが LDO に表示される場合、出力を生成する目的では、それぞれが単一のリンク関係タイプを持つが、それ以外は同一の複数の LDO として扱われます。
targetUri
ターゲットリソースの完全に解決された URI(スキーム付き)。リンクが入力を受け入れる場合、これは入力が提供された後にのみ生成できます。
hrefInputTemplates
入力を受け入れるリンクに対して部分的に解決された URI 参照のリスト。リストの最初のエントリは、部分的に解決された「href」です。追加のエントリ(ある場合)は、最も直接的なものからスキーマのルートまで順序付けられた、部分的に解決された「base」の値です。入力に事前に入力されているテンプレート変数は、事前に入力された値を上書きできるため、この段階では解決されません。
hrefPrepopulatedInput
クライアント入力を受け入れる前に、ユーザーエージェントが入力メカニズムに事前に入力するために使用する必要があるデータセット。入力を受け入れる必要があるが、事前に入力するフィールドがない場合、これは空のオブジェクトになります。
attachmentPointer
リンクが添付されているインスタンス内の場所の JSON ポインター。デフォルトでは、「contextUri」と「attachmentPointer」は同じですが、「contextUri」は LDO キーワードで変更できますが、「attachmentPointer」は変更できません。

上記の情報を生成することに関与しないその他の LDO キーワードは、テストスイートの出力を生成する際に表示されるとおりに正確に含まれます。これらのフィールドは、特に重要な場合を除き、ここではこれ以上議論しません。

7.1. リンクの発見と検索

リンクを使用する前に、ハイパースキーマをインスタンスに適用し、適用可能で有効なすべてのリンクを見つけることによって、リンクを発見する必要があります。有効なリンクを収集することに加えて、各 LDO の URI テンプレートを解決するために必要な「base」の値もすべて特定し、実装の URI テンプレート解決プロセスに最も役立つメカニズムを介して LDO に関連付ける必要があることに注意してください。

実装は、添付ポインターまたはコンテキストポインターのいずれかによってリンクを検索することをサポートする必要があります。検索を実行するか、ユーザーエージェントが検索自体を実装できるように、両方のポインターが決定されたすべてのリンクのセットを提供する必要があります。

コンテキストポインターによる検索を実行する場合、同じ配列の要素に添付されたリンクは、それらが添付されている配列要素と同じ順序で返される必要があります。

7.2. URI テンプレート

3 つのハイパースキーマキーワードは、URI テンプレートです。「base」、「anchor」、および「href」です。それぞれが個別に URI 参照に解決され、次に、アンカーまたは href URI 参照がベースに対して解決されます(ベース自体は必要に応じて以前のベースに対して解決され、そのそれぞれは最初に URI テンプレートから URI 参照に解決されました)。

3 つのキーワードはすべて、インスタンスデータから変数を解決するための同じアルゴリズムを共有しており、このアルゴリズムは「templatePointers」および「templateRequired」キーワードを使用します。「href」を解決する場合、絶対 URI への解決に必要な「base」テンプレートとともに、アルゴリズムは「hrefSchema」キーワードに基づいてオプションでユーザー入力を受け入れるように変更されます。

各 URI テンプレート(T)について、次の疑似コードは、T を URI 参照(R)に解決するためのアルゴリズムを記述しています。このアルゴリズムの目的のために

このアルゴリズムは、最初に「href」または「anchor」のいずれかに適用し、次に必要に応じて各連続する「base」に適用する必要があります。テンプレートが完全な URI に解決されるか、URI 参照に解決されるかを常に判断できるとは限らないため、順序が重要です。

英語で言うと、高レベルのアルゴリズムは次のとおりです。

  1. インスタンスからテンプレート変数データを入力する
  2. 入力が必要な場合は、入力を受け入れる
  3. 必要なすべての変数に値があることを確認する
  4. 値を文字列にエンコードし、テンプレートを入力する

これは、疑似コードとしての高レベルのアルゴリズムです。「T」は、LDO 内の「href」または「anchor」から、または包含スキーマの「base」から取得されます。各ステップの疑似コードが続きます。「initialTemplateKeyword」は、どちらがプロセスを開始したかを示します(「base」は、これらのキーワードのいずれかを解決するために常に順番に解決されるため)。

templateData = populateDataFromInstance(T, ldo, instance)

if initialTemplateKeyword == "href" and ldo.hrefSchema exists:
    inputData = acceptInput(ldo, instance, templateData)
    for varname in inputData:
        templateData[varname] = inputData[varname]

for varname in ldo.templateRequired:
    if not exists templateData[varname]
        fatal("Missing required variable(s)")

templateData = stringEncode(templateData)
R = rfc6570ResolutionAlgorithm(T, templateData)

                    

7.2.1. インスタンスからテンプレートデータを入力する

このステップでは、変数値をインスタンス内のさまざまな場所で検索します。各変数について

  1. 変数がそのキーワードの値に表示される場合は、「templatePointers」を使用して値を検索する
  2. それ以外の場合は、リンクが添付されているインスタンスの場所で変数と一致するプロパティ名を検索する
  3. どちらの場合も、その場所に値がある場合は、テンプレート解決データセットに入れる

for varname in T:
    varname = rfc3986PercentDecode(varname)
    if varname in ldo.templatePointers:
        valuePointer = templatePointers[varname]
        if valuePointer is relative:
            valuePointer = resolveRelative(attachmentPointer,
                                           valuePointer)
    else
        valuePointer = attachmentPointer + "/" + varname

    value = instance.valueAt(valuePointer)
    if value is defined:
        templateData[varname] = value

                        

7.2.2. テンプレートデータの入力を受け入れる

このステップは、サポートするケースがいくつかあるため、比較的複雑です。一部の変数は入力を禁止し、一部は入力を許可します。入力インターフェイスに表示する必要のある初期値を持つものもあれば、そうでないものもあります。

  1. 入力を受け入れることができる変数を決定する
  2. テンプレート解決データセットに値がある場合は、入力データセットを事前に入力する
  3. 入力を受け入れる(Webフォームを提示する、コールバックを行うなど)
  4. 入力データセットを検証する(テンプレート解決データセットではない)
  5. テンプレート解決データセットに入力を入れ、既存の値を上書きする

「InputForm」は、適切な入力メカニズムの種類を表します。これは、リテラルの Web フォームである場合もあれば、特定のフィールドとデータ型を受け入れるコールバック関数のような、よりプログラム的な構成である場合もあります(指定された初期値がある場合)。

form = new InputForm()
for varname in T:
    useField = true
    useInitialData = true
    for schema in getApplicableSchemas(ldo.hrefSchema,
                                       "/" + varname):
        if schema is false:
            useField = false
            break

        if varname in templateData and
           not isValid(templateData[varname], schema)):
            useInitialData = false
            break

    if useField:
        if useInitialData:
            form.addInputFieldFor(varname, ldo.hrefSchema,
                                  templateData[varname])
        else:
            form.addInputFieldFor(varname, ldo.hrefSchema)

inputData = form.acceptInput()

if not isValid(inputData, hrefSchema):
    fatal("Input invalid, link is not usable")

return inputData:

                        

7.2.3. データを文字列としてエンコードする

このセクションは簡単で、リテラルを文字列としての名前、数値を最も明らかな方法で文字列に変換し、必要に応じて URI で使用するためにパーセントエンコーディングします。

for varname in templateData:
    value = templateData[varname]
    if value is true:
        templateData[varname] = "true"
    else if value is false:
        templateData[varname] = "false"
    else if value is null:
        templateData[varname] = "null"
    else if value is a number:
        templateData[varname] =
            bestEffortOriginalJsonString(value)
    else:
        templateData[varname] = rfc3986PercentEncode(value)

                        

一部のソフトウェア環境では、数値の元の JSON 表現は利用できません(1.0 と 1 の違いを判別する方法はありません)。そのため、合理的な表現を使用する必要があります。スキーマと API の作成者は、これを念頭に置き、正確な表現が重要な場合は、他の型(文字列やブールなど)を使用する必要があります。数値が文字列形式で入力として提供された場合は、入力として使用された文字列を使用する必要があります。

7.3. LDO キーワードへのアクセスを提供する

特定のリンクについて、実装は、すべてのターゲット属性キーワードの値をユーザーエージェントが直接利用できるようにする必要があります。実装は、各キーワードのセクションで説明されているように、この情報を使用するための追加のインターフェイスを提供する場合があります(MAY)。

特定のリンクについて、実装は、各入力スキーマキーワードの値をユーザーエージェントが直接利用できるようにする必要があります。

URI テンプレートの解決プロセスのカプセル化を促進するために、実装は、URI の構築にのみ使用される LDO キーワードを省略できます(MAY)。ただし、実装は、リンク関係タイプへのアクセスを提供する必要があります。

認識されないキーワードは、ユーザーエージェントが利用できるようにする必要があり(SHOULD)、それ以外の場合は無視する必要があります(MUST)。

7.4. リクエスト

ハイパースキーマの実装は、対象リソースへの有効なリクエストを構築するために必要なすべての情報へのアクセスを提供すべきです(SHOULD)。

LDOは、リンクに対するあらゆる操作を実行するために必要なすべての情報を表現できます。このセクションでは、インスタンスデータとクライアント入力を任意に組み合わせてリクエストを構築するために、ユーザーエージェントが調べるべきハイパースキーマのフィールドについて説明します。ハイパースキーマの実装自体は、リクエストを構築して送信することを期待されていません。

入力受付用の "hrefSchema" を含む、ターゲットURI構築規則は、可能なすべてのリクエストで同一です。

ボディペイロードを伴わないリクエストは、追加のキーワードサポートを必要としません。

ターゲット表現をペイロードとして受け取るリクエストは、入力記述とペイロード検証のために、"targetSchema" および "targetMediaType" キーワードを使用すべきです(SHOULD)。プロトコルが、メディアタイプによって変更された表現に基づいたペイロードを受け取る操作(パッチメディアタイプなど)を許可する場合、そのようなメディアタイプは、プロトコル固有の方法で "targetHints" を通じて示されるべきです(SHOULD)。

ターゲットリソースの表現から派生しないペイロードを受け取るリクエストは、入力記述とペイロード検証のために、"submissionSchema" および "submissionMediaType" キーワードを使用すべきです(SHOULD)。ハイパーメディアで使用されるプロトコルは、一般的に、リンクごとに1つの非表現操作のみをサポートします。

単一のハイパーメディアプロトコル操作を通じて、任意に異なるリクエスト構造を持つ多くのアプリケーション操作をパイプするRPCシステムは、JSONハイパースキーマのようなハイパーメディア形式の範囲外です。

7.5. レスポンス

ハイパーメディア形式として、JSONハイパースキーマは、すべての有効なリクエストを作成するための詳細を含めて、リソースを記述することに関心があります。それらのリクエストに対するすべての可能なレスポンスを直接記述することには関心がありません。

すべてのハイパーメディアシステムと同様に、レスポンスは自己記述的であることが期待されます。ハイパースキーマのコンテキストでは、これは、各レスポンスが自身のハイパースキーマにリンクする必要がある(MUST)ことを意味します。ターゲットリソースの表現で構成されるレスポンスは、"targetSchema" および "targetMediaType" に対して有効であることが期待されますが、これらのキーワードは助言に過ぎず、レスポンス自体によって矛盾している場合は無視されなければなりません(MUST)。

エラーレスポンス、複雑なリダイレクション、および処理ステータス表現を含むその他のレスポンスも、自身のスキーマにリンクし、適切なメディアタイプを使用すべきです(SHOULD)(エラーの場合は"application/problem+json"など)。特定のエラーは、オリジンではなく、ハイパースキーマを認識しない仲介者によって生成されるため、スキーマをリンクしない場合があります。

ユーザーエージェントは、一般的な状況を処理するのに十分なほどプロトコルのステータスコードとレスポンスのメディアタイプを理解し、ドメイン固有のレスポンスを処理するためにクライアントアプリケーションに十分な情報を提供することが期待されます。

設計時に可能なすべてのレスポンスとそれらのスキーマを静的にマッピングすることは、JSONハイパースキーマの範囲外ですが、ハイパースキーマを基盤とする他のJSONスキーマ語彙の範囲内である可能性があります(付録 A.3を参照)。

7.6. ストリーミングパーサー

コンテキストに基づいてリンクを発見したり、リンクのコンテキストを使用してコレクションを識別したりすることに関する要件は、ストリーミングパーサーで使用する場合に独自の問題を提起します。スキーマとインスタンスドキュメント全体を処理せずに、これらの要件を権威をもって満たすことはできません。

このような実装は、これまでに処理されたデータに基づいて非権威的な回答を返すことを選択してもよい(MAY)。このアプローチを提供する場合は、実装はレスポンスの性質を明確にする必要があり(MUST)、すべてのデータが処理され、権威ある回答を返すことができるまでブロックして待機するオプションを提供する必要があります(MUST)。

8. JSONハイパースキーマとHTTP

JSONハイパースキーマはハイパーメディア形式であり、したがってプロトコルに依存しませんが、最も一般的な使用は、HTTPシステム、またはHTTPに明示的に類似したCoAPなどのプロトコルを使用するシステムであることが期待されます。

このセクションでは、各一般的なHTTPメソッドをリンクとともに使用する方法と、コレクションリソースがHTTP POSTに課す追加の制約についてガイダンスを提供します。さらに、HTTPレスポンスヘッダー値のヒントと、特定のリソースに関連する可能性のあるHTTPリクエストヘッダーを記述するためのガイダンスを提供します。

JSONスキーマコア仕様のセクション13は、ハイパーメディアシステムのインスタンスをそれらのスキーマにリンクする方法に関するガイダンスを提供します。これは、ネットワークアクセス可能なスキーマを使用して行うことも、クライアントアプリケーションにプリパッケージされたスキーマを単に識別することもできます。JSONハイパースキーマは、このメカニズムを意図的に制約しませんが、コア仕様で概説されている手法を可能な限り使用することが推奨されます(RECOMMENDED)。

8.1. ターゲットと関係タイプごとの1つのリンク

リンク記述オブジェクトは、HTTPメソッドなどの操作がターゲットリソースでサポートされているかどうかを直接示しません。代わりに、操作は主にリンクの関係タイプとURIスキームから推測されるべきです。

これは、ターゲットリソースとリンク関係タイプのペアごとに、スキーマ作成者は単一のLDOのみを定義すべきである(SHOULD)ことを意味します。"targetHints" で "allow" を使用して、許可されたHTTPメソッドが異なる関係タイプとターゲットペアを繰り返すことは可能ですが、これは推奨されません(NOT RECOMMENDED)であり、準拠実装では十分にサポートされない可能性があります。

このセクションで説明するように、各HTTPメソッドを使用するために必要なすべての情報は、単一のLDOで伝達できます。"targetHints" の "allow" フィールドは、サポートされている操作を単に示唆することを目的としており、各操作を個別に定義することを目的としていません。

ただし、リソースは、たとえば承認の失敗や、操作の可用性を制御する他のアプリケーションの状態により、実行時に操作を拒否する可能性があります。

8.2. "targetSchema" と HTTP

"targetSchema" は、リンクのターゲット側のリソースを記述し、"targetMediaType" はそのリソースのメディアタイプを定義します。HTTPリンクでは、"headerSchema" を使用して、複数のメディアタイプまたはメディア範囲をサポートできる "Accept" リクエストヘッダーで使用する有効な値を記述することもできます。ターゲットメディアタイプを示す両方の方法が存在する場合、"targetMediaType" はデフォルトの表現メディアタイプを示す必要があり(SHOULD)、"headerSchema" の "accept" のスキーマは、デフォルトに加えて、要求できる代替メディアタイプまたはメディア範囲を含める必要があります(SHOULD)。

多くのHTTPメソッドのセマンティクスはターゲットリソースに関して定義されているため、"targetSchema" はいくつかのHTTPメソッドのリクエストおよび/またはレスポンスに使用されます。特に、"targetSchema" は、HTTP GETへのレスポンス、または "Content-Location" ヘッダーがリクエストURIと等しいレスポンスに対してクライアントアプリケーションが期待できるもの、およびクライアントアプリケーションがHTTP PUTリクエストでリソースを作成または置換する場合に送信する必要があるものを示唆します。これらの相関関係は、RFC 7231、セクション 4.3.1 - "GET"、セクション 4.3.4 "PUT"、およびセクション 3.1.4.2 "Content-Location" で定義されています。

RFC 5789に従って、HTTP PATCHのリクエスト構造は、"targetSchema" とリクエストメディアタイプの組み合わせによって決定されます。このメディアタイプは、"Accept-Patch" ヘッダーによって伝えられ、"targetHints" に含めることができます。PATCHに適したメディアタイプは、ドキュメントへの変更を表現するための構文を定義します。これは、"targetSchema" で記述された表現に適用して、構文的に有効なリクエストペイロードのセットを決定できます。多くの場合、PATCHリクエストを検証する最も簡単な方法は、それを適用し、結果を通常の表現として検証することです。

8.3. HTTP POST と "submission*" キーワード

JSONハイパースキーマでは、ターゲットの表現を操作する代わりに、またはそれに加えて、任意にデータを処理するリソースを許可します。この任意のデータは、"submissionSchema" および "submissionMediaType" キーワードで記述されます。HTTPの場合、POSTメソッドはこのようなデータを処理する唯一のメソッドです。コレクションでPOSTを使用することに関する特定の規則がありますが、POSTリクエストのセマンティクスはHTTPではなく、ターゲットリソースによって定義されます。

プロトコルに依存しない "submission*" キーワードに加えて(HTTP以外の例についてはセクション 9.3を参照)、"Accept-Post" ヘッダーを使用して必要なメディアタイプを指定でき、"targetHints" フィールドを介してアドバタイズしてもよい(MAY)。[CREF4]両方が使用された場合はどうなりますか? また、"submissionSchema" はサポートする必要があり(MUST)、"targetHints" はせいぜい(at most) SHOULDです。しかし、"targetHints" で "Accept-Post" を使用することを禁止するのは正しくないようです。

"Content-Location" が設定された201または200以外のPOSTに対する成功レスポンスも同様に、HTTP定義のセマンティクスはありません。すべてのHTTPレスポンスと同様に、レスポンス内の表現は、どのように処理できるかを示すために、独自のハイパースキーマにリンクする必要があります。付録 A.2で述べたように、すべての可能な操作レスポンスとハイパーリンクを接続することは、JSONハイパースキーマの範囲内ではありません。

8.4. "targetHints" を使用したHTTPの検出可能性の最適化

[CREF5]CoAPの例を含むセクションも含めるのが良いでしょう。

HTTPレスポンスヘッダー情報のJSONシリアル化は、進行中の"HTTPヘッダーフィールド値のJSONエンコーディング"で確立されたガイドラインに従う必要があり(SHOULD)、そのドキュメントの例に示されているアプローチは、可能な限り他の同様に構造化されたヘッダーに適用する必要があります。

すべての可能なHTTPメソッドレスポンスのヘッダーはすべて "headerSchema" を共有します。特に、HEADレスポンスに表示されるヘッダーと、OPTIONSレスポンスに表示されるヘッダーの両方が表示される可能性があります。"headerSchema" 内では、どのメソッドレスポンスにどのヘッダーが含まれているかについて区別されません。

スキーマ作成者は、適用可能な場合は常に、次のタイプのHTTPヘッダーの値のヒントを提供することが推奨されます(RECOMMENDED)。

一般に、異なる時点で異なる値を持つ可能性が高いヘッダーは、"targetHints" に含めるべきではありません(SHOULD NOT)。

例として、HEAD、GET、およびPOSTを許可するAllowヘッダーは、次のように表示されます。

{
    "targetHints": {
        "allow": ["HEAD", "GET", "POST"]
    }
}

                    

これは、カンマ区切りの値を持つ単一行のAllowヘッダーがある場合、複数のAllowヘッダーが別々の行にあり、それぞれに1つの値がある場合、またはそのような配置の任意の組み合わせがある場合でも、同一に表現されることに注意してください。HTTPヘッダーで一般的に当てはまるように、カンマ区切りの値とヘッダーの複数の出現は同じように扱われます。

8.5. "headerSchema" を使用したHTTP機能のアドバタイズ

スキーマは、進行中の"HTTPヘッダーフィールド値のJSONエンコーディング"で確立されたガイドラインに従うJSONシリアル化を記述するように記述する必要があり(SHOULD)、そのドキュメントの例に示されているアプローチは、可能な限り他の同様に構造化されたヘッダーに適用する必要があります。

スキーマ作成者は、適用可能な場合は常に、次のタイプのHTTPヘッダーの利用可能な使用法を記述することが推奨されます(RECOMMENDED)。

キャッシュ制御ヘッダーや条件付きリクエストヘッダーなどのヘッダーは、一般にリソースではなく仲介者によって実装されるため、記述するのに一般的に役立ちません。リソースは条件付きリクエストを使用するために必要な情報を提供する必要がありますが、そのようなヘッダーと関連するレスポンスのランタイム処理はリソース固有ではありません。

8.6. コレクションを介したリソースの作成

HTTP、またはHTTPに明示的に類似したCoAPなどのプロトコルを使用する場合、これは、作成される個々のリソースの表現をコレクションリソースにPOSTすることによって行われます。コレクションリソースとアイテムリソースを認識するプロセスは、セクション 6.2.3 で説明されています。

8.7. コンテンツネゴシエーションとスキーマの進化

JSON Hyper-Schema は HTTP コンテンツネゴシエーションを促進し、プロアクティブ戦略とリアクティブ戦略のハイブリッドを可能にします。前述のように、ハイパースキーマは "headerSchema" キーワードを用いて、"Accept"、"Accept-Charset"、"Accept-Language" などの HTTP ヘッダーのスキーマを含めることができます。ユーザーエージェントやクライアントアプリケーションは、このスキーマ内の情報(例えば、サポートされている言語の列挙リスト)を利用して、リアクティブなネゴシエーションプロセスを開始するための初期リクエストを回避できます。

このようにして、これらのヘッダーを設定するプロアクティブなコンテンツネゴシエーション技術は、リアクティブなネゴシエーションにおける代替案のリストを調べるのと同様に、可能な値に関するサーバー情報に基づいたものにすることができます。

スキーマをメディアタイプパラメーターとして指定できるメディアタイプの場合、リクエストで送信される、または "headerSchema" でアドバタイズされる "Accept" の値には、ネゴシエートされた表現が準拠することが期待されるスキーマの URI を含めることができます。コンテンツネゴシエーションにおけるスキーマパラメーターの考えられる用途の1つは、リソースが時間経過とともにいくつかの異なるスキーマバージョンに準拠してきた場合です。クライアントアプリケーションは、この方法で "Accept" ヘッダーで理解できるバージョンを示すことができます。

9.

このセクションでは、URI と JSON ポインターを構成するキーワードの使用方法を示します。結果はテストスイートで使用される形式で表示されます。 [CREF6]それを投稿してリンクする必要がありますが、この段階でレビューしている皆様には非常にわかりやすいはずです。

他のほとんどのキーワードは、単純("title" や "description")であるか、特定の種類の入力、リクエスト、またはレスポンスに検証を適用するか、プロトコル固有の動作を持ちます。HTTP の使用法を示す例は、付録にあります。

9.1. エントリポイントリンク、テンプレートなし

この例では、ドキュメント化されたエントリポイント URI が https://example.com/api である API の例を想定します。これは、スキーマへのリンクを持つ空の JSON オブジェクトです。ここで、エントリポイント自体にはデータがなく、リンクの初期セットを提供するためだけに存在します。

GET https://example.com/api HTTP/1.1

200 OK
Content-Type: application/json
Link: <https://schema.example.com/entry>; rel="describedBy"
{}

                    

リンクされたハイパースキーマは、API のベース URI を定義し、2 つのリンクを提供します。API ドキュメントへの "about" リンクと、これがベース URI のスキーマであることを示す "self" リンクです。

{
    "$id": "https://schema.example.com/entry",
    "$schema": "https://json-schema.dokyumento.jp/draft/2019-09/hyper-schema",
    "base": "https://example.com/api/",
    "links": [
        {
            "rel": "self",
            "href": "../api",
        }, {
            "rel": "about",
            "href": "docs"
        }
    ]
}
                    

これらは、関係タイプと、テンプレート変数を持たない "href" のみを持つ、最も単純なリンクです。それらは次のように解決されます。

"self" リンクのベースと "../api" href の両方での "api" の重複は、RFC 3986 URI 参照解決アルゴリズムの癖によるものです。相対 URI 参照が一般的にうまく機能するためには、ベース URI に末尾のスラッシュを含める必要があります。"about" リンクとその "docs" href は、このドキュメントの他の例で使用されている、相対参照の一般的なケースを示しています。

ただし、API がリソースに末尾のスラッシュのない URI を使用する場合、末尾のスラッシュを削除するだけの相対参照を、上のパスコンポーネントを複製せずに提供する方法はありません。これは、末尾のスラッシュの点でのみベース URI と異なるエントリポイントリソースの場合を、多少ぎこちなくします。

もちろん、リソース URI には末尾のスラッシュを含めることができますが、この例は、この頻繁に混乱する特殊なケースを強調することを目的としています。

[
    {
        "contextUri": "https://example.com/api",
        "contextPointer": "",
        "rel": "self",
        "targetUri": "https://example.com/api",
        "attachmentPointer": ""
    },
    {
        "contextUri": "https://example.com/api",
        "contextPointer": "",
        "rel": "about",
        "targetUri": "https://example.com/api/docs",
        "attachmentPointer": ""
    }
]
                    

添付ポインターはルートポインターです(インスタンスの空のオブジェクトでの唯一の可能性)。コンテキスト URI はデフォルトであり、リクエストされたドキュメントです。application/json はフラグメントを許可していないため、コンテキストを完全に記述するにはコンテキストポインターが必要です。そのデフォルトの動作は、添付ポインターと同じです。

9.2. 個別に識別されるリソース

システムの「物」を追加してみましょう。まず、個々の物から始めます。

{
    "$id": "https://schema.example.com/thing",
    "$schema": "https://json-schema.dokyumento.jp/draft/2019-09/hyper-schema",
    "base": "https://example.com/api/",
    "type": "object",
    "required": ["data"],
    "properties": {
        "id": {"$ref": "#/$defs/id"},
        "data": true
    },
    "links": [
        {
            "rel": "self",
            "href": "things/{id}",
            "templateRequired": ["id"],
            "targetSchema": {"$ref": "#"}
        }
    ],
    "$defs": {
        "id": {
            "type": "integer",
            "minimum": 1,
            "readOnly": true
        }
    }
}
                    

「物」にはサーバーによって割り当てられた ID があり、"self" リンクを構築するために必要です。また、任意の型にできる "data" フィールドがあります。"$defs" セクションの理由は、次の例で明らかになります。

"id" は検証スキーマでは必須ではありませんが、self リンクでは必須であることに注意してください。これは理にかなっています。「物」が URI を持つのは、作成された場合のみであり、サーバーが ID を割り当てた場合です。ただし、データフィールドのみを含むインスタンスでこのスキーマを使用できます。これにより、作成しようとしている「物」のインスタンスを検証できます。

入力を ID として指定できる場合に、特定の物に直接ジャンプできるリンクをエントリポイントスキーマに追加しましょう。スペースを節約するために、新しい LDO のみが表示されます。"self" や "about" とは異なり、仮説的な物に関する IANA に登録された関係はないため、"tag:" URI スキームを使用して拡張関係を定義します。

{
    "rel": "tag:rel.example.com,2017:thing",
    "href": "things/{id}",
    "hrefSchema": {
        "required": ["id"],
        "properties": {
            "id": {"$ref": "thing#/$defs/id"}
        }
    },
    "targetSchema": {"$ref": "thing#"}
}
                    

ここでの "href" 値は同じですが、その他はすべて異なります。インスタンスは空のオブジェクトであるため、"id" はインスタンスデータから解決できないことを思い出してください。代わりに、クライアント入力として必要になります。この LDO では "templateRequired" を使用することもできますが、"hrefSchema" で "required" が使用されているため、厳密には必要ありません。"hrefSchema" で "id" を必須としてマークせずに "templateRequired" を提供すると、クライアント入力がこのリンクを解決するための唯一の可能なソースであるため、エラーが発生します。

9.3. ペイロードの送信と URI 入力の受け入れ

この例では、非表現入力に "submission" フィールドを使用する方法と、入力を使用して URI テンプレートを解決する方法について説明します。URI を構築するか、ペイロードを送信する必要がある HTML フォームとは異なり、JSON ハイパースキーマは、同じリンクに対する同じ操作に対して両方の種類の入力を記述できます。

"submissionSchema" フィールドと "submissionMediaType" フィールドは、ターゲットリソースの表現ではないペイロードを記述するためのものです。"http(s)://" URI と共に使用すると、通常、HTTP の使用に関する付録にあるように、POST リクエストペイロードを指します。

この場合、RFC 6068, Section 3に従って、リソースを取得する操作を提供しない "mailto:" URI を使用します。送信するメッセージを構築するためにのみ使用できます。取得、置換、または削除可能なターゲットリソースの概念がないため、"targetSchema" と "targetMediaType" は使用されません。非表現ペイロードは、"submissionSchema" と "submissionMediaType" によって記述されます。

"submissionMediaType" を使用して、同じデータの 2 つの表現(HTML とプレーンテキスト)を提供する multipart/alternative ペイロード形式を示します。multipart/alternative メッセージは順序付けられたシーケンスであるため(最後の部分が最も優先される代替案です)、"submissionSchema" でシーケンスを配列としてモデル化します。各パート自体がメディアタイプを持つドキュメントであるため、配列内の各項目を文字列としてモデル化し、文字列内の形式を示すために "contentMediaType" を使用します。

各パートに名前が関連付けられ、順序付けられていない multipart/form-data などのメディアタイプは、配列ではなく JSON オブジェクトとしてモデル化する必要があることに注意してください。

一部の行は、このドキュメントの幅の制限に収まるように折り返されています。

{
    "$id": "https://schema.example.com/interesting-stuff",
    "$schema": "https://json-schema.dokyumento.jp/draft/2019-09/hyper-schema",
    "required": ["stuffWorthEmailingAbout", "email", "title"],
    "properties": {
        "title": {
            "type": "string"
        },
        "stuffWorthEmailingAbout": {
            "type": "string"
        },
        "email": {
            "type": "string",
            "format": "email"
        },
        "cc": false
    },
    "links": [
        {
            "rel": "author",
            "href": "mailto:{email}?subject={title}{&cc}",
            "templateRequired": ["email"],
            "hrefSchema": {
                "required": ["title"],
                "properties": {
                    "title": {
                        "type": "string"
                    },
                    "cc": {
                        "type": "string",
                        "format": "email"
                    },
                    "email": false
                }
            },
            "submissionMediaType":
                    "multipart/alternative; boundary=ab2",
            "submissionSchema": {
                "type": "array",
                "items": [
                    {
                        "type": "string",
                        "contentMediaType":
                                "text/plain; charset=utf8"
                    },
                    {
                        "type": "string",
                        "contentMediaType": "text/html"
                    }
                ],
                "minItems": 2
            }
        }
    ]
}
                    

URI パラメーターの場合、3 つそれぞれが異なる入力解決方法を示します。

email
"templateRequired" にこの変数が存在するということは、テンプレートを使用するには解決する必要があることを意味します。"hrefSchema" で割り当てられた "false" スキーマによって入力データセットから除外されるため、インスタンスから解決する必要があります。
title
この変数に一致するインスタンスフィールドは必須であり、入力データでも許可されています。したがって、インスタンス値は、クライアント入力を受け入れる前に、入力データセットを事前に入力するために使用されます。クライアントアプリケーションは、インスタンス値をそのまま残すことを選択できます。このフィールドは "hrefSchema" で必須であるため、クライアントアプリケーションは削除できません(ただし、空の文字列に設定することはできます)。
cc
メインスキーマでこれに設定された "false" スキーマは、このフィールドがインスタンス値を持つことを防ぎます。存在する場合、クライアント入力から取得する必要があります。"hrefSchema" では必須ではないため、まったく使用されない可能性があります。

したがって、"https://example.com/api/stuff" から取得した次のインスタンスが与えられた場合

{
    "title": "The Awesome Thing",
    "stuffWorthEmailingAbout": "Lots of text here...",
    "email": "[email protected]"
}
                    

クライアントアプリケーションに入力を要求する前に、次のようにリンクを部分的に解決できます。

{
    "contextUri": "https://example.com/api/stuff",
    "contextPointer": "",
    "rel": "author",
    "hrefInputTemplates": [
      "mailto:[email protected]?subject={title}{&cc}"
    ],
    "hrefPrepopulatedInput": {
        "title": "The Awesome Thing"
    },
    "attachmentPointer": ""
}
                    

"targetUri" の代わりに "href*" キーワードに注意してください。これらは、さまざまな種類の入力をカバーする 3 つの可能な "targetUri" 値です。以下にそれぞれの例を示します。

追加または変更された入力なし
"mailto:[email protected]?subject=The%20Awesome%20Thing"
"title" を "your work" に変更
"mailto:[email protected]?subject=your%20work"
タイトルを変更し、"cc" を "[email protected]" に追加
"mailto:[email protected]?subject=your%20work&[email protected]"

9.4. "anchor"、"base" および URI テンプレートの解決

リンクは、コンテキストリソースからターゲットリソースへの型付き接続です。古いリンクシリアル化では、"rel" と同様にリンク関係タイプを取得する "rev" キーワードをサポートしますが、セマンティクスを反転します。これは長い間非推奨になっているため、JSON ハイパースキーマではサポートされていません。代わりに、"anchor" のコンテキスト URI を変更する機能を使用して、リンクの方向を反転させることができます。また、現在のリソースではない 2 つのリソース間のリンクを記述するために使用することもできます。

例として、IANA に登録された "up" 関係がありますが、"down" はありません。HTTP Link ヘッダーでは、"rev": "up" として "down" を実装できます。

まず、これを HTTP でどのように行うかを見てみましょう。"self" リンクと意味的に同一の 2 つのリンクを表示します。1 つは "rev": "up" で、もう 1 つは "rel": "up" を持つ "anchor" を使用しています(フォーマット上の制限により折り返されています)。

GET https://example.com/api/trees/1/nodes/123 HTTP/1.1

200 OK
Content-Type: application/json
Link: <https://example.com/api/trees/1/nodes/123>; rel="self"
Link: <https://example.com/api/trees/1/nodes/123>; rel="up";
        anchor="https://example.com/api/trees/1/nodes/456"
Link: <https://example.com/api/trees/1/nodes/456>; rev="up"
{
    "id": 123,
    "treeId": 1,
    "childIds": [456]
}

                    

"rel=up" リンクは "rel=self" リンクと同一のターゲット URI を持ち、"anchor"(リンクのコンテキストを識別します)を子 URI に設定していることに注意してください。この種の反転されたリンクは、"self" リンクも存在する場合、ツールによって簡単に検出できます。

以下のハイパースキーマを、上記のレスポンスのインスタンスに適用すると、「self」リンクと「up」リンクが「anchor」付きで生成されます。また、テンプレート化された「base」URIの使用と、「templatePointers」における絶対および相対JSONポインターの両方の使用を示しています。

{
    "$id": "https://schema.example.com/tree-node",
    "$schema": "https://json-schema.dokyumento.jp/draft/2019-09/hyper-schema",
    "base": "trees/{treeId}/",
    "properties": {
        "id": {"type": "integer"},
        "treeId": {"type": "integer"},
        "childIds": {
            "type": "array",
            "items": {
                "type": "integer",
                "links": [
                    {
                        "anchor": "nodes/{thisNodeId}",
                        "rel": "up",
                        "href": "nodes/{childId}",
                        "templatePointers": {
                            "thisNodeId": "/id",
                            "childId": "0"
                        }
                    }
                ]
            }
        }
    },
    "links": [
        {
            "rel": "self",
            "href": "nodes/{id}"
        }
    ]
}
                    

「base」テンプレートは、ターゲット(「href」)URIとコンテキスト(「anchor」)URIの両方に対して同一に評価されます。

使用されている2種類の異なるtemplatePointersに注目してください。「thisNodeId」は絶対JSONポインター「/id」にマッピングされ、「childId」は現在のアイテムの値を表す相対ポインター「0」にマッピングされます。絶対JSONポインターはワイルドカードをサポートしていないため、相対JSONポインターなしには「現在のアイテム」のような概念を指定する方法はありません。

9.5. コレクション

多くのシステムでは、個々のリソースがコレクションにグループ化されています。これらのコレクションは、サーバーが割り当てた識別子を持つ個々のアイテムリソースを作成する方法も提供することがよくあります。

この例では、前のセクションで示した個々のthingスキーマを再利用します。便宜上、ここに再掲し、次に紹介するコレクションスキーマを指す「targetSchema」参照を持つ「collection」リンクを追加します。

{
    "$id": "https://schema.example.com/thing",
    "$schema": "https://json-schema.dokyumento.jp/draft/2019-09/hyper-schema",
    "base": "https://example.com/api/",
    "type": "object",
    "required": ["data"],
    "properties": {
        "id": {"$ref": "#/$defs/id"},
        "data": true
    },
    "links": [
        {
            "rel": "self",
            "href": "things/{id}",
            "templateRequired": ["id"],
            "targetSchema": {"$ref": "#"}
        }, {
            "rel": "collection",
            "href": "/things",
            "targetSchema": {"$ref": "thing-collection#"},
            "submissionSchema": {"$ref": "#"}
        }
    ],
    "$defs": {
        "id": {
            "type": "integer",
            "minimum": 1,
            "readOnly": true
        }
    }
}
                    

「collection」リンクはすべてのアイテムで同じであるため、URIテンプレート変数はありません。「submissionSchema」はアイテム自体のスキーマです。6.2.3節で説明したように、「collection」リンクが送信メカニズム(HTTPのPOST)をサポートする場合、アイテム作成セマンティクスを実装する必要があります。したがって、「submissionSchema」はこのリンクを介して「thing」を作成するためのスキーマです。

次に、「thing」のコレクションについて説明します。このスキーマは、各アイテムの表現が個々の「thing」の表現と同一であるコレクションを表しています。多くのコレクション表現にはアイテム表現のサブセットのみが含まれますが、この例では関与するスキーマの数を最小限に抑えるために全体を使用しています。実際のコレクションアイテムは、オブジェクト内の配列として表示されます。次の例では、オブジェクトにさらにフィールドを追加します。

{
    "$id": "https://schema.example.com/thing-collection",
    "$schema": "https://json-schema.dokyumento.jp/draft/2019-09/hyper-schema",
    "base": "https://example.com/api/",
    "type": "object",
    "required": ["elements"],
    "properties": {
        "elements": {
            "type": "array",
            "items": {
                "allOf": [{"$ref": "thing#"}],
                "links": [
                    {
                        "anchorPointer": "",
                        "rel": "item",
                        "href": "things/{id}",
                        "templateRequired": ["id"],
                        "targetSchema": {"$ref": "thing#"}
                    }
                ]
            }
        }
    },
    "links": [
        {
            "rel": "self",
            "href": "things",
            "targetSchema": {"$ref": "#"},
            "submissionSchema": {"$ref": "thing"}
        }
    ]
}
                    

これは、シンプルな2要素コレクションインスタンスです。

{
    "elements": [
        {"id": 12345, "data": {}},
        {"id": 67890, "data": {}}
    ]
}
                    

以下は、参照されている個々の「thing」スキーマで定義されているものも含め、このインスタンスに適用されるすべてのリンクです。

[
    {
        "contextUri": "https://example.com/api/things",
        "contextPointer": "",
        "rel": "self",
        "targetUri": "https://example.com/api/things",
        "attachmentPointer": ""
    },
    {
        "contextUri": "https://example.com/api/things",
        "contextPointer": "/elements/0",
        "rel": "self",
        "targetUri": "https://example.com/api/things/12345",
        "attachmentPointer": "/elements/0"
    },
    {
        "contextUri": "https://example.com/api/things",
        "contextPointer": "/elements/1",
        "rel": "self",
        "targetUri": "https://example.com/api/things/67890",
        "attachmentPointer": "/elements/1"
    },
    {
        "contextUri": "https://example.com/api/things",
        "contextPointer": "",
        "rel": "item",
        "targetUri": "https://example.com/api/things/12345",
        "attachmentPointer": "/elements/0"
    },
    {
        "contextUri": "https://example.com/api/things",
        "contextPointer": "",
        "rel": "item",
        "targetUri": "https://example.com/api/things/67890",
        "attachmentPointer": "/elements/1"
    },
    {
        "contextUri": "https://example.com/api/things",
        "contextPointer": "/elements/0",
        "rel": "collection",
        "targetUri": "https://example.com/api/things",
        "attachmentPointer": "/elements/0"
    },
    {
        "contextUri": "https://example.com/api/things",
        "contextPointer": "/elements/1",
        "rel": "collection",
        "targetUri": "https://example.com/api/things",
        "attachmentPointer": "/elements/1"
    }
]

                    

すべての場合において、コンテキストURIはフラグメントをサポートしないメディアタイプapplication/jsonのインスタンスに対して表示されます。インスタンスのメディアタイプがJSONポインターフラグメントをサポートするapplication/instance+jsonの場合、コンテキストURIにはコンテキストポインターフィールドと同一のフラグメントが含まれます。application/jsonやフラグメントを持たない他のメディアタイプの場合、コンテキストURIだけでなく、コンテキストポインターも考慮することが非常に重要です。

「self」リンクは3つあります。1つはコレクション用、残りの2つは「elements」配列内の各アイテム用です。アイテムの「self」リンクは、「$ref」で参照される個々の「thing」スキーマで定義されています。3つのリンクは、コンテキストまたは添付ポインターによって区別できます。コレクションの「self」リンクの「submissionSchema」については、9.5.2節で再検討します。

「item」リンクは2つあります。「elements」配列内の各アイテムに1つずつです。「self」リンクとは異なり、これらはコレクションスキーマでのみ定義されています。それらの各々は、同じ添付ポインターを共有する対応する「self」リンクと同じターゲットURIを持ちます。ただし、それぞれ異なるコンテキストポインターを持ちます。「self」リンクのコンテキストは「elements」のエントリーですが、「item」リンクのコンテキストは特定のアイテムに関係なく常にコレクション全体です。

最後に、「collection」リンクは2つあります。「elements」内の各アイテムに1つずつです。個々のアイテムスキーマでは、これらはアイテムリソースをコンテキストとするリンクを生成します。コレクションスキーマから参照される場合、コンテキストは「thing」独自の個別リソースURIではなく、「elements」配列内の関連する「thing」の位置です。

コレクションリンクは、関連するコレクションURIが1つしかないため、同一のターゲットURIを持ちます。構築されたリンクの完全なセットの一部として両方のリンクを計算することが有用ではないように思えるかもしれませんが、必要に応じてリンクを構築する場合、この配置は、どの「elements」エントリーを処理しているかに関係なく、「collection」リンク定義が手元にあることを意味します。

9.5.1. ページネーション

ここでは、コレクションにページネーションを追加します。「meta」セクションには、現在、次、前のページに関する情報が保持されます。スキーマのほとんどは前のセクションと同じであり、省略されています。新しいフィールドと、新しいリンク(またはメインの「self」リンクの場合は変更されたリンク)のみが完全に表示されます。

{
    "properties": {
        "elements": {
            ...
        },
        "meta": {
            "type": "object",
            "properties": {
                "prev": {"$ref": "#/$defs/pagination"},
                "current": {"$ref": "#/$defs/pagination"},
                "next": {"$ref": "#/$defs/pagination"}
            }
        }
    },
    "links": [
        {
            "rel": "self",
            "href": "things{?offset,limit}",
            "templateRequired": ["offset", "limit"],
            "templatePointers": {
                "offset": "/meta/current/offset",
                "limit": "/meta/current/limit"
            },
            "targetSchema": {"$ref": "#"}
        }, {
            "rel": "prev",
            "href": "things{?offset,limit}",
            "templateRequired": ["offset", "limit"],
            "templatePointers": {
                "offset": "/meta/prev/offset",
                "limit": "/meta/prev/limit"
            },
            "targetSchema": {"$ref": "#"}
        }, {
            "rel": "next",
            "href": "things{?offset,limit}",
            "templateRequired": ["offset", "limit"],
            "templatePointers": {
                "offset": "/meta/next/offset",
                "limit": "/meta/next/limit"
            },
            "targetSchema": {"$ref": "#"}
        }
    ],
    "$defs": {
        "pagination": {
            "type": "object",
            "properties": {
                "offset": {
                    "type": "integer",
                    "minimum": 0,
                    "default": 0
                },
                "limit": {
                    "type": "integer",
                    "minimum": 1,
                    "maximum": 100,
                    "default": 10
                }
            }
        }
    }
}
                        

「self」リンクには、入力でページを選択できるコレクションへの一般的なリンクではなく、正確な表現を生成したページネーションクエリが含まれていることに注意してください。

このインスタンスを考えると

{
    "elements": [
        {"id": 12345, "data": {}},
        {"id": 67890, "data": {}}
    ],
    "meta": {
        "current": {
            "offset": 0,
            "limit": 2
        },
        "next": {
            "offset": 3,
            "limit": 2
        }
    }
}
                        

以下は、前の例には表示されなかった、またはページネーションが追加されて変更されたこのインスタンスに適用されるすべてのリンクです。

[
    {
        "contextUri": "https://example.com/api/things",
        "contextPointer": "",
        "rel": "self",
        "targetUri":
            "https://example.com/api/things?offset=0&limit=2",
        "attachmentPointer": ""
    },
    {
        "contextUri": "https://example.com/api/things",
        "contextPointer": "",
        "rel": "next",
        "targetUri":
            "https://example.com/api/things?offset=3&limit=2",
        "attachmentPointer": ""
    }
]
                        

最初のページを見ているため、出力に「prev」リンクがないことに注意してください。「meta」の下に「prev」フィールドがないことと、「prev」リンクの「templateRequired」の値が、この特定のインスタンスではリンクを使用できないことを意味します。

[CREF7]個々の「thing」スキーマの「collection」リンクからのリンクでページネーションがどのように機能するかは明確ではありません。技術的には、アイテムからページネーションされたまたはフィルタリングされたコレクションへのリンクは、リンクコンテキストであるアイテム(この場合は「thing」)を含むページ/フィルターに移動する必要があります。詳細については、GitHub issue #421を参照してください。

クライアントアプリケーションが特定のページに直接ジャンプできるように、ページネーション入力を含めて、このコレクションのエントリーポイントスキーマ(9.1節)へのリンクを追加しましょう。エントリーポイントスキーマはリンクのみで構成されているため、新しく追加されたリンクのみを示します。

{
    "rel": "tag:rel.example.com,2017:thing-collection",
    "href": "/things{?offset,limit}",
    "hrefSchema": {
        "$ref": "thing-collection#/$defs/pagination"
    },
    "submissionSchema": {
        "$ref": "thing#"
    },
    "targetSchema": {
        "$ref": "thing-collection#"
    }
}
                        

ページネーションパラメーターが入力として受け入れられるようになったため、コレクション内の任意のページにジャンプできます。リンク関係タイプは、汎用「collection」リンクをアイテムをコンテキストとしてのみ使用できるため、カスタムのものです。エントリポイントまたは他のリソースではありません。

9.5.2. 最初のアイテムの作成

「thing」がない場合、関連する「collection」リンクを持つリソースはありません。したがって、「collection」リンクの送信キーワードを使用して最初の「thing」を作成することはできません。ハイパースキーマはインスタンスに関して評価される必要があります。コレクションインスタンスの「elements」配列は空であるため、コレクションリンクを提供することもできません。

ただし、エントリポイントリンクは空のコレクションに移動することができ、ハイパースキーマ内の「item」リンクの存在を使用して、それがコレクションであることを認識できます。「item」リンクのコンテキストはコレクションであるため、同じコンテキストを持つ「self」リンクを探し、それを作成操作の目的でコレクションとして扱うことができます。

おそらく、エントリポイントスキーマのカスタムリンク関係タイプは、正しいコレクションを見つけるのに十分でした。カスタムリンク関係タイプを認識するクライアントアプリケーションは、ターゲットがコレクションであるとすぐに想定できることを知っている可能性がありますが、汎用ユーザーエージェントはそうすることができません。例では「-collection」サフィックスが存在しますが、汎用ユーザーエージェントは、そのサブストリングがハイパーメディアリソースコレクションまたは他の種類のコレクションを示しているかどうかを知る方法はありません。

「self」リンクが正しいコレクション用であると認識したら、その「submissionSchema」および/または「submissionMediaType」キーワードを使用してアイテム作成操作を実行できます。[CREF8]コレクションがフィルタリングされておらず、ページネーションされていない場合は、これは完全に機能します。ただし、一般的に、作成されたリソースを含むコレクションにPOSTする必要があり、「self」リンクには、フィルター、ページネーション、またはその他のクエリパラメーターを含める必要があります。結果のアイテムがフィルターに一致しない場合やそのページに表示されない場合でも、このような「self」リンクにPOSTすることは引き続き有効ですか?詳細については、GitHub issue #421を参照してください。 [CREF9]ハイパースキーマのドラフト04では、「create」リンク関係が定義されており、コンテキストとしてインスタンスではなくスキーマがありました。これはインスタンスベースのリンクモデルに適合せず、リンク関係タイプに操作名を誤って使用しました。ただし、スキーマからコレクションインスタンスへのより適切に設計されたリンクを定義することは、これを解決するための1つの可能なアプローチとなる可能性があります。詳細については、GitHub issue #421を参照してください。

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

JSONハイパースキーマは、JSONスキーマコアのボキャブラリーを定義し、そこに記載されているすべてのセキュリティに関する考慮事項に関係します。リンクシリアル化形式として、RFC 8288 Web Linkingのセキュリティに関する考慮事項も、適切な調整(たとえば、「anchor」はHTTP Linkヘッダー属性ではなくLDOキーワードとして)を加えて適用されます。

10.1. ターゲット属性

6.5節で述べたように、ターゲットリソースを記述するすべてのLDOキーワードは推奨事項であり、操作への応答としてターゲットリソースから提供される信頼できる情報の代わりに使用してはなりません。ターゲットリソースの応答は、信頼できるハイパースキーマを示す必要があります。

ターゲット応答のハイパースキーマが、現在のLDOが見つかったハイパースキーマと(「$id」によって)一致する場合、ターゲット属性は信頼できると見なされる場合があります。[CREF10]「$id」によるなりすましのリスクについて何かを追加する必要がありますが、仕様の他の部分がリンクされたスキーマを常に再ダウンロードすることを推奨していないことを考えると、リスク軽減の選択肢は不明確です。

ユーザーエージェントまたはクライアントアプリケーションは、「targetSchema」の値を使用して、リンクをたどったことに対する応答で受信したデータの解釈を支援してはなりません。これは、「安全な」データが再解釈される可能性があるためです。

データを解釈する方法を選択する場合、サーバーから提供された(またはファイル名から推測された、またはその他の通常の方法から推測された)タイプ情報のみを考慮する必要があり、リンクの「targetMediaType」プロパティは使用してはなりません。ユーザーエージェントは、この情報を使用して、リンクの表現方法や表示場所(たとえば、ホバーテキスト、新しいタブで開く)を決定できます。ユーザーエージェントがリンクを外部プログラムに渡すことを決定した場合、最初にデータが通常その外部プログラムに渡されるタイプであることを確認する必要があります。

これは、「targetSchema」の注意と同様に、「安全な」データの再解釈を防ぐためです。

「targetHints」で伝達されるプロトコルメタデータ値は、信頼できると見なしてはなりません。メタデータ値に関する不正確な仮定に基づいて適用される可能性のある、プロトコルによって定義されたセキュリティに関する考慮事項が適用されます。

プロトコルのセキュリティに関する考慮事項が直接適用されない場合でも、実装はリンクの「targetHints」値と一致しない応答を処理する準備ができている必要があります。

10.2. 「self」リンク

リンク関係 "self" がオブジェクトの完全な表現を示すために使用される場合、ユーザーエージェントは、そのターゲット URI が、"self" リンクを含むリソース表現を要求するために使用された URI と同等でない、またはそのサブパスでない場合は、その表現をターゲット URI で示されるリソースの正式な表現と見なすべきではありません。[CREF11]この段落の「サブパス」オプションの意図が何であったかは、もはや完全には明らかではありません。コレクション内の埋め込みアイテムの表現に「self」リンクを許可し、それらのターゲット URI が通常、コレクションの URI のサブパスである場合に、それらを正式なものと見なすことを意図していた可能性があります。しかし、これは単に一般的な設計上の慣例であり、RFC 3986 や URI の使用に関するその他のガイダンスに基づいているようには見えません。詳細については、GitHub issue #485 を参照してください。

11. 謝辞

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、Denis Laxalde に感謝します。

12. 参考文献

12.1. 規定の参考文献

[json-schema] Wright, A. および H. Andrews, "JSON Schema: JSONドキュメントを記述するためのメディアタイプ", Internet-Draft draft-handrews-json-schema-02, 2017年11月.
[json-schema-validation] Wright, A., Andrews, H. および G. Luff, "JSON Schema Validation: JSONの構造検証のための語彙", Internet-Draft draft-handrews-json-schema-validation-02, 2017年11月.
[relative-json-pointer] Luff, G. および H. Andrews, "相対JSONポインタ", Internet-Draft draft-handrews-relative-json-pointer-02, 2018年1月.
[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): 一般的な構文", STD 66, RFC 3986, DOI 10.17487/RFC3986, 2005年1月.
[RFC4287] Nottingham, M. および R. Sayre, "Atom Syndication Format", RFC 4287, DOI 10.17487/RFC4287, 2005年12月.
[RFC6570] Gregorio, J., Fielding, R., Hadley, M., Nottingham, M. および D. Orchard, "URIテンプレート", RFC 6570, DOI 10.17487/RFC6570, 2012年3月.
[RFC6573] Amundsen, M., "アイテムとコレクションのリンク関係", RFC 6573, DOI 10.17487/RFC6573, 2012年4月.
[RFC6901] Bryan, P., Zyp, K. および M. Nottingham, "JavaScript Object Notation (JSON) ポインタ", RFC 6901, DOI 10.17487/RFC6901, 2013年4月.
[RFC8288] Nottingham, M., "Web Linking", RFC 8288, DOI 10.17487/RFC8288, 2017年10月.

12.2. 参考となる参考文献

[I-D.reschke-http-jfv] Reschke, J., "HTTPヘッダーフィールド値のJSONエンコーディング", Internet-Draft draft-reschke-http-jfv-06, 2017年6月.
[RFC2046] Freed, N. および N. Borenstein, "Multipurpose Internet Mail Extensions (MIME) Part Two: Media Types", RFC 2046, DOI 10.17487/RFC2046, 1996年11月.
[RFC4151] Kindberg, T. および S. Hawke, "'tag' URIスキーム", RFC 4151, DOI 10.17487/RFC4151, 2005年10月.
[RFC5789] Dusseault, L. および J. Snell, "HTTPのPATCHメソッド", RFC 5789, DOI 10.17487/RFC5789, 2010年3月.
[RFC6068] Duerst, M., Masinter, L. および J. Zawinski, "'mailto' URIスキーム", RFC 6068, DOI 10.17487/RFC6068, 2010年10月.
[RFC7230] Fielding, R. および J. Reschke, "Hypertext Transfer Protocol (HTTP/1.1): メッセージ構文とルーティング", RFC 7230, DOI 10.17487/RFC7230, 2014年6月.
[RFC7231] Fielding, R. および J. Reschke, "Hypertext Transfer Protocol (HTTP/1.1): セマンティクスとコンテンツ", RFC 7231, DOI 10.17487/RFC7231, 2014年6月.
[RFC7807] Nottingham, M. および E. Wilde, "HTTP APIの問題詳細", RFC 7807, DOI 10.17487/RFC7807, 2016年3月.

付録 A. APIでのJSONハイパースキーマの使用

RESTアーキテクチャスタイルの制約に従うハイパーメディアAPIは、汎用的なユーザーエージェントの作成を可能にします。このようなユーザーエージェントは、アプリケーション固有の知識を持っていません。むしろ、事前に定義されたメディアタイプ、URIスキーム、プロトコル、およびリンク関係を理解しており、多くの場合、これらを認識し、それらのサポートを実装する既存のソフトウェアの使用を調整します。クライアントアプリケーションは、相互作用のメカニズムではなく、独自のセマンティクスとロジックに焦点を当てて、このようなユーザーエージェントの上に構築できます。

ハイパースキーマは、一度に1つのリソースと関連リンクのセットのみを対象とします。Webブラウザが一度に1つのHTMLページのみを処理し、そのページが「サイト」の一部として機能するかどうか、またはどのように機能するかという概念がないのと同じように、ハイパースキーマ対応のユーザーエージェントは、そのリソースがAPIに適合するかどうかという概念なしに、一度に1つのリソースを処理します。

したがって、ハイパースキーマはAPI内での使用に適していますが、APIをそれ自体で完全なエンティティとして記述するのには適していません。リソースおよびリンクのスコープではなく、APIスコープで概念を記述する方法はなく、そのような記述はJSONハイパースキーマの境界外です。

A.1. ハイパースキーマによるリソースの進化

特定のJSONハイパースキーマは、単一の時点で単一のリソースで使用されるため、バージョン管理の固有の概念はありません。ただし、特定のリソースは、時間の経過とともに使用するスキーマを変更でき、これらのスキーマのURIを使用して、バージョン管理情報を示すことができます。メディアタイプパラメータでスキーマを示すことをサポートするメディアタイプで使用する場合、これらのバージョン管理されたスキーマURIをコンテンツネゴシエーションで使用できます。

リソースは、複数のスキーマのインスタンスであることを示すことができ、これにより、複数の互換性のあるバージョンを同時にサポートできます。クライアントアプリケーションは、認識するハイパースキーマを利用し、新しいバージョンまたは古いバージョンを無視できます。

A.2. レスポンスとエラー

ハイパースキーマは一度に1つのリソースを表すため、リンクを使用したプロトコル操作に対するすべての可能なレスポンスの列挙を提供しません。エラーを含む各レスポンスは、独自の(おそらく匿名の)リソースと見なされ、独自のハイパースキーマを識別し、オプションでRFC 7807の "application/problem+json"などの適切なメディアタイプを使用して、ユーザーエージェントまたはクライアントアプリケーションがプロトコル自身のステータスレポートを超えて提供される情報を解釈できるようにする必要があります。

A.3. APIのハイパースキーマの静的解析

ドキュメントやコードなどの出力を生成するために、インスタンスデータなしで一連のハイパースキーマを静的に解析できます。ただし、検証とハイパースキーマの両方の完全な機能セットは、ランタイムインスタンスデータなしではアクセスできません。

これは、ハイパーメディアシステムの最大限のランタイム柔軟性を提供するための意図的な設計上の選択です。メディアタイプとしてのJSON Schemaは、この仕様では扱われていない静的解析およびコンテンツ生成のための追加の語彙を確立することを可能にします。さらに、個々のシステムは、完全な設計時記述が目標である場合に、静的に解析できるサブセットに制限する場合があります。[CREF12]APIドキュメントおよびその他の目的のための語彙が提案されており、https://github.com/json-schema-org/json-schema-vocabularies での貢献を歓迎します。

付録 B. 変更履歴

[CREF13]このセクションは、インターネットドラフトのステータスを離れる前に削除されます。

draft-handrews-json-schema-hyperschema-02

draft-handrews-json-schema-hyperschema-01

draft-handrews-json-schema-hyperschema-00

draft-wright-json-schema-hyperschema-01

draft-wright-json-schema-hyperschema-00

draft-luff-json-hyper-schema-00

著者の住所

Henry Andrews (編集者) メール: [email protected]
Austin Wright (編集者) メール: [email protected]