インターネット技術タスクフォース H. Andrews 編
インターネットドラフト Cloudflare, Inc.
意図されたステータス:参考情報 A. Wright 編
期限切れ:2018年5月24日 2017年11月20日

JSONハイパー・スキーマ:JSONのハイパーメディアアノテーションのためのボキャブラリ
draft-handrews-json-schema-hyperschema-00

要約

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)の作業文書です。他のグループもインターネットドラフトとして作業文書を配布する場合があることに注意してください。現在のインターネットドラフトの一覧は、http://datatracker.ietf.org/drafts/current/にあります。

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

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

著作権表示

Copyright (c) 2017 IETF Trustおよびドキュメントの著者として特定されている個人。全著作権所有。

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


目次

1. はじめに

JSONハイパー・スキーマは、HTTPなどのハイパーメディア環境を通じてリモートJSONリソースの処理と操作に関する指示とハイパーリンクを用いてJSONドキュメントに注釈を付けるためのJSONスキーマボキャブラリです。

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

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

この仕様では、JSONスキーマコア [json-schema]およびJSONスキーマ検証 [json-schema-validation]仕様によって定義されている概念、構文、および用語を使用します。読者はこれらの仕様のコピーを持っていることをお勧めします。

2. 表記規則

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

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 [RFC3986]による基本URIが"https://api.example.com/"の場合、「https://api.example.com/thing/1234」は結果として得られるリンクのターゲットURIです。

3.1. 用語

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

「適用可能」および「添付」という用語は、JSONスキーマ検証仕様のセクション3 [json-schema-validation]で定義されているように解釈されます。

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

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

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

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

3.2. 機能

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

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

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

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

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

[CREF1]「draft-07-wip」はプレースホルダーです。

JSONハイパーシェマメタスキーマの現在のURIは<https://json-schema.dokyumento.jp/draft-07/hyper-schema#>です。

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

JSONハイパーシェマの実装は、任意の形式で出力を提供できます。ただし、適合性テストスイートで使用される特定の形式が定義されており、これは"実装要件" [implementation]のポイントを説明するためにも使用され、 [examples]によって生成された出力を示すためにも使用されます。テストを容易にするために、実装がこの形式の出力を生成できることが推奨されます。推奨される出力形式を記述するJSONスキーマのURIは<https://json-schema.dokyumento.jp/draft-07/hyper-schema-output#>です。

5. スキーマキーワード

JSONスキーマ検証のセクション3 [json-schema-validation]で定義されているように、インスタンス内の位置に適用可能なすべてのスキーマからのハイパーシェマキーワードを、そのインスタンスで使用できます。

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

すべてのJSONスキーマキーワードと同様に、このセクションで説明されているすべてのキーワードはオプションです。最小限有効なJSONハイパーシェマは空のオブジェクトです。

5.1. base

存在する場合、このキーワードはまずURIテンプレートとして解決 [uriTemplating]され、次にインスタンスの現在のURIベースに対してURI参照として解決される必要があります。結果は、"base"を含むサブスキーマとその中のすべてのサブスキーマを処理している間、インスタンスの新しいURIベースとして設定する必要があります。

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

5.2. links

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

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

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

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

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

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

6.1. リンクコンテキスト

JSONハイパーシェマでは、リンクのコンテキストリソースは、デフォルトで、それにアタッチされているサブインスタンスです(JSONスキーマ検証仕様のセクション3 [json-schema-validation]で定義されています)。これは多くの場合、インスタンスドキュメント全体ではありません。このデフォルトのコンテキストは、このセクションのキーワードを使用して変更できます。

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

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

6.1.1. anchor

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

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

6.1.2. anchorPointer

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

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

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

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

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

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

リレーション定義は通常、メディアタイプに依存せず、ユーザーは既存の承認済みリレーション定義の中で最も適切なものを利用することが推奨されます。

6.2.1. rel

このプロパティの値は文字列で**なければならず**、RFC 8288、セクション 2.1で定義されている単一のリンクリレーションタイプで**なければなりません**。

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

6.2.2. "self" リンク

RFC 4287のセクション 4.2.7.2 [RFC4287]で最初に定義された "self" リンクは、ターゲットURIがリンクコンテキストと等価なリソースを識別することを示します。JSON ハイパーメディアスキーマでは、"self" リンクはインスタンスから解決可能で**なければならず**、そのため "hrefSchema" は存在して**はなりません**。

ハイパーメディアスキーマの作成者は、"self" リンクに必要なインスタンスデータがすべて揃うように "templateRequired" を使用する**べきです**。

ハイパーメディアスキーマの実装は、リレーションタイプが "self" であり、現在のインスタンスドキュメント全体をコンテキストとして持つリンクが、ユーザーエージェントがそのインスタンスドキュメントによって表されるリソースとどのように対話できるかを記述していることを認識する**必要があります**。

6.2.3. "collection" と "item" リンク

RFC 6573 [RFC6573] は "item" と "collection" リンクリレーションタイプを定義し、登録しています。JSON ハイパーメディアスキーマは、これらのタイプによって示されるコレクションリソースにさらなるセマンティクスを課します。

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

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

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

6.2.4. 拡張リレーションタイプの使用

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

拡張リレーションタイプURIは、スキームがそれを許可している場合でも、デリファレンス可能である必要はありません。

6.3. リンクターゲット

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

6.3.1. href

"href" リンク記述プロパティの値は、関連リソースのターゲットURIを決定するために使用されるテンプレートです。インスタンスプロパティの値は、インスタンスのベースURIに対してURI参照 [RFC3986]として解決され**なければなりません**。

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

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

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

"base" テンプレートを解決する場合、解決が開始されるアタッチメントポイントは、"base" テンプレートを必要とする "href" または "anchor" キーワードのアタッチメントポイントであり、"base" キーワード自体のアタッチメントポイントではありません。

6.4.1. templatePointers

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

解決されるテンプレート内の変数名と一致するオブジェクトのプロパティ名ごとに、そのプロパティの値はその変数の変数解決の開始位置を調整します。解決されるテンプレート内のテンプレート変数名と一致しないプロパティは無視され**なければなりません**。

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 [RFC2046]を表します。このプロパティの値は、RFC 7231、セクション 5.3.2 - HTTP "Accept" ヘッダー [RFC7231]で定義されているのと同じパターンを使用して、メディア範囲である場合もあります。

このプロパティは、他のリンクシリアル化形式の "type" プロパティと類似しています。ユーザーエージェントは、リンクがたどられる前に、ユーザーに提示するインターフェースを知らせるためにこの情報を使用しても**構いません**が、結果データの解釈にはこの情報を使用して**はなりません**。代わりに、ユーザーエージェントは、実行時の解釈には応答によって与えられるメディアタイプを使用する**必要があります**。"セキュリティに関する懸念事項" [security] セクションで、"targetMediaType" の誤用について詳しく調べることができます。

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

そのようなプロトコル固有の情報がない場合、または実装が関係するプロトコルを認識しない場合、値は "application/json" とする**べきです**。

6.5.4. targetSchema

このプロパティは、リンクターゲットの表現を記述すると予想されるスキーマを提供します。プロトコルによっては、スキーマはリンクを使用して実行される特定の操作に対する要求または応答を記述する場合と記述しない場合があります。このキーワードがHTTPでどのように使用されるかについては、JSON ハイパーメディアスキーマとHTTP [HTTP]セクションで詳しく説明しています。

6.5.5. targetHints

[CREF2]このセクションは、その構造の大部分をURIスキームによって示されるプロトコルに委任することによって、包括性と柔軟性のバランスを取ろうとしています。リソースはデリファレンス可能なスキームを持つURIによって識別できますが、そのプロトコル経由でアクセスできないことに注意してください。現在非常に緩やかですが、このセクションはドラフトのフィードバックに基づいてより明確になり、将来のドラフトで大幅に変更される可能性があります。

このプロパティの値は助言のみです。これは、ターゲットリソースと対話することで検出できることが期待される情報を表し、通常はHTTP HEADまたはOPTIONS要求への応答で返されるヘッダーなどのプロトコル固有の制御情報またはメタデータの形式です。プロトコルは "href" URIスキームによって決定されますが、リソースがそのようなプロトコル経由でアクセスできるとは限らないことに注意してください。

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

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

指示されたプロトコルの範囲内で解釈できない値は、JSONハイパー・スキーマの実装において無視されなければなりません。アプリケーションはこれらの値を利用しても構いませんが、他の実装との相互運用性を想定してはなりません。

実装は、このオブジェクトにすべての検出可能な情報が含まれていると想定してはなりません。クライアントアプリケーションは、このプロパティの値と矛盾する実行時応答を適切に処理しなければなりません。

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

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

6.6. リンク入力

リンクでクライアント入力を利用する方法は4つあり、それぞれが個別のリンク記述オブジェクトキーワードによって扱われます。操作を実行する際には、ユーザーエージェントは、そのセマンティクスに関連しないスキーマを無視するべきです。

6.6.1. hrefSchema

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

"hrefSchema"を省略するか、スキーマ全体を"false"に設定すると、ユーザーエージェントデータの受け入れが防止されます。

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

インスタンスデータから解決できるテンプレート変数について、インスタンスデータが"hrefSchema"内のすべての適用可能なサブスキーマに対して有効な場合、その変数の入力データセットの事前設定に使用されなければなりません。

インスタンスからデータが事前設定されている場合でも、"hrefSchema"内のその変数の検証スキーマは、インスタンスデータの場所に適用される検証スキーマと同一である必要はありません。これにより、日付時刻入力で完全な月の表記をサポートするなど、ユーザーエージェントデータに対する異なる検証ルールを適用しながら、標準的な日付時刻形式を保存に使用することができます。

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

6.6.2. headerSchema

[CREF3]"targetHints"と同様に、柔軟性と明確さのバランスを取るために、このキーワードはやや不十分に規定されています。実験とフィードバックを奨励するためです。

存在する場合、このプロパティは、プロトコル固有の要求ヘッダーまたは類似のコントロールとメタデータのためのスキーマです。このオブジェクトの値は、有効なJSONスキーマでなければなりません。プロトコルは"href" URIスキームによって決定されますが、リソースがそのようなプロトコル経由でアクセス可能であることは保証されていません。スキーマは助言的なものであり、ターゲットリソースの動作は、その存在によって制約されません。

このキーワードの目的は、ターゲットリソースのインタラクション機能を広告し、ユーザーエージェントとクライアントアプリケーションに、どのヘッダーとヘッダー値が役立つ可能性が高いかを示すことです。ユーザーエージェントとクライアントアプリケーションは、スキーマを使用して関連するヘッダーを検証しても構いませんが、ヘッダーまたは値がないことを禁止されていると想定してはなりません。スキーマ作成者は"additionalProperties"をfalseに設定しても構いませんが、これは推奨されず、クライアントアプリケーションまたはユーザーエージェントが要求を行う際に追加のヘッダーを提供することを妨げてはなりません。

JSONデータモデルからヘッダーへの正確なマッピングは、プロトコルに依存します。ただし、ほとんどの場合、このスキーマは"object"型を指定するべきであり、プロパティ名はコントロールデータフィールド名の小文字形式であるべきです。HTTPおよび類似プロトコルでのこのキーワードの使用に関する詳細なガイダンスについては、"JSONハイパー・スキーマとHTTP" [HTTP]セクションを参照してください。

"headerSchema"は、プロトコルがサポートする任意の要求メソッドまたはコマンドに適用されます。要求を生成する際には、ユーザーエージェントとクライアントアプリケーションはその要求に関連しないヘッダーのスキーマを無視するべきです。

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

JSONハイパー・スキーマでは、"targetSchema" [targetSchema]は、ターゲットリソースの表現に関する権威のない記述を提供します。クライアントアプリケーションは"targetSchema"を使用して、表現の置換または変更のための入力を構成したり、パッチメディアタイプに基づいてパッチドキュメントを構築するための基本表現として使用したりできます。

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

"targetSchema"は、応答のセマンティクスがターゲットリソースの表現であることを示している場合を除き、リンク操作の応答を記述することを意図していません。いずれの場合も、応答自体によって示されるスキーマが権威のあるものです。"JSONハイパー・スキーマとHTTP" [HTTP]に詳細な例があります。

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

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

6.6.4.1. submissionMediaType

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

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

"submissionMediaType"と"submissionSchema"はHTTP URIに限定されません。[CREF4]この記述は、例が最終的に配置される場所に移動される可能性があります。

6.6.4.2. submissionSchema

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

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

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

7. 実装要件

高いレベルでは、準拠する実装は次の要件を満たします。これらの要件はそれぞれ、個々のキーワードセクションとキーワードグループの概要でより詳細に説明されています。

実装がどのように"self"、"collection"、"item"リンクを認識しなければならないかについての要件は、リンク関係タイプ [relationType]セクションで徹底的に説明されており、ここでは繰り返しません。

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

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

上記の情報の生成に関与しないその他のLDOキーワードは、テストスイートの出力を作成する場合とまったく同じように含まれます。それらのフィールドについては、特に関連しない限り、ここではさらに説明しません。

7.1. リンクの検出と検索

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

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

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

7.2. URIテンプレート

3つのハイパー schema キーワードは、URIテンプレート [RFC6570]:「base」、「anchor」、「href」です。それぞれがURI参照に個別に解決され、次にanchorまたはhref URI参照がbaseに対して解決されます(必要に応じて以前のbaseに対して解決されます。それぞれは最初に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. 入力を受け入れます(ウェブフォームを表示する、コールバックを行うなど)
  4. 入力データセットを検証します(テンプレート解決データセットではありません)
  5. 既存の値を上書きして、入力データセットをテンプレート解決データセットに入れます

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

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:
        temlateData[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キーワードへのアクセスを提供する

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

指定されたリンクについて、実装は、各入力スキーマキーワードの値をユーザーエージェントに直接利用可能にする必要があります。

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

認識されないキーワードは、ユーザーエージェントに利用可能にする必要があります。それ以外の場合は無視する必要があります。

7.4. 要求

ハイパー schema 実装は、ターゲットリソースへの有効な要求を作成するために必要なすべての情報へのアクセスを提供する必要があります。

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

入力を受け入れるための「hrefSchema」を含むターゲットURI構築ルールは、可能なすべての要求で同一です。

本文ペイロードを運ばない要求は、追加のキーワードサポートを必要としません。

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

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

任意の異なる要求構造を持つ多くのアプリケーション操作を単一のハイパーメディアプロトコル操作を介してパイプするRPCシステムは、JSONハイパー schema などのハイパーメディア形式の範囲外です。

7.5. 応答

ハイパーメディア形式として、JSONハイパー schema は、すべての有効な要求を行うのに十分な詳細さでリンクを記述することを含め、リソースを記述することに関係しています。これらの要求に対するすべての可能な応答を直接記述することには関係ありません。

任意のハイパーメディアシステムと同様に、応答は自己記述的であることが期待されます。ハイパー schema のコンテキストでは、これは各応答が独自のハイパー schema をリンクする必要があることを意味します。ターゲットリソースの表現からなる応答は「targetSchema」と「targetMediaType」に対して有効であることが期待されますが、これらのキーワードはアドバイザリのみであり、応答自体と矛盾する場合は無視する必要があります。

エラー応答、複雑なリダイレクト、処理状況表現など、他の応答も、独自のスキーマにリンクし、適切なメディアタイプ(例:"application/problem+json" [RFC7807] エラーの場合)を使用する必要があります。ハイパー schema を認識していない中間体によって生成されたものではなく、オリジンによって生成されたため、特定のエラーはスキーマにリンクされない場合があります。

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

設計時に可能なすべての応答とそのスキーマを静的にマッピングすることは、JSONハイパー schema の範囲外ですが、ハイパー schema を基盤とする他のJSONスキーマボキャブラリ(付録A.3を参照)の範囲内にある可能性があります。

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

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

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

8. JSONハイパー schema とHTTP

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

このセクションでは、各一般的なHTTPメソッドをリンクで使用する方法、およびコレクションリソースがHTTP POSTに追加の制約を課す方法について説明します。さらに、HTTP応答ヘッダー値をヒントし、指定されたリソースに関連する可能性のあるHTTP要求ヘッダーについて説明するガイダンスが提供されます。

JSONスキーマコア仕様のセクション11 [json-schema] は、ハイパーメディアシステム内のインスタンスをスキーマにリンクする方法について説明しています。これはネットワークアクセス可能なスキーマで行うことも、クライアントアプリケーションに事前にパッケージ化されたスキーマを単純に識別することもできます。JSONハイパー schema は意図的にこのメカニズムを制約しませんが、コア仕様で概説されている手法を可能な限り使用することをお勧めします。

8.1. ターゲットとリレーションタイプごとに1つのリンク

リンク記述オブジェクトは、ターゲットリソースによってサポートされているHTTPメソッドなどの操作を直接示しません。代わりに、操作は主にリンクリレーションタイプ [rel]とURIスキームから推測する必要があります。

これは、各ターゲットリソースとリンクリレーションタイプペアに対して、スキーマ作成者は単一のLDOのみを定義するべきであることを意味します。「allow」と「targetHints」を使用して、許可されたHTTPメソッドが異なるリレーションタイプとターゲットペアを繰り返すことは可能ですが、これは推奨されず、準拠実装で十分にサポートされない可能性があります。

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

ただし、認可の失敗や操作の可用性を制御するその他のアプリケーション状態など、実行時にリソースが常に操作を拒否することがあることに注意してください。

8.2. "targetSchema"とHTTP

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

多くの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" [RFC7231]で定義されています。

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

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

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

プロトコルに依存しない「submission*」キーワード(非HTTPの例についてはセクション9.3を参照)に加えて、「Accept-Post」ヘッダーを使用して必要なメディアタイプを指定でき、「targetHints」フィールドを介して広告することもできます。[CREF5]両方が使用された場合はどうなるのでしょうか?また、「submissionSchema」はサポートするために必須ですが、「targetHints」はせいぜい推奨事項です。「Accept-Post」を「targetHints」で使用することを禁止するのは正しくないように思われます。

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

8.4. "targetHints"によるHTTP検出可能性の最適化

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

HTTPレスポンスヘッダー情報のJSONシリアライゼーションは、進行中の作業"A JSON Encoding for HTTP Header Field Values" [I-D.reschke-http-jfv]で確立されたガイドラインに従う必要があります。そのドキュメントの例に示されているアプローチは、可能な限り、同様に構造化された他のヘッダーにも適用する必要があります。

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

スキーマ作成者は、該当する場合は、次のタイプのHTTPヘッダーの値のヒントを提供することを推奨します。

一般的に、異なる時間に異なる値を持つ可能性のあるヘッダーは、「targetHints」に含めないでください。

8.5. "headerSchema"によるHTTP機能の広告

スキーマは、進行中の作業"A JSON Encoding for HTTP Header Field Values" [I-D.reschke-http-jfv]で確立されたガイドラインに従うJSONシリアライゼーションを記述するように記述する必要があります。そのドキュメントの例に示されているアプローチは、可能な限り、同様に構造化された他のヘッダーにも適用する必要があります。

スキーマ作成者は、該当する場合は、次のタイプのHTTPヘッダーの使用可能な使用方法を記述することを推奨します。

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

8.6. コレクションによるリソースの作成

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

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

JSON Hyper-SchemaはHTTPコンテンツネゴシエーションを容易にし、プロアクティブ戦略とリアクティブ戦略のハイブリッドを許可します。上記のように、ハイパースキーマには、「headerSchema」キーワードを使用して、「Accept」、「Accept-Charset」、「Accept-Language」などのHTTPヘッダーのスキーマを含めることができます。ユーザーエージェントまたはクライアントアプリケーションは、サポートされている言語の列挙されたリストなど、このスキーマの情報を使用して、リアクティブネゴシエーションプロセスを開始するための最初のリクエストを行う代わりに使用できます。

このように、これらのヘッダーを設定するプロアクティブなコンテンツネゴシエーション手法は、可能な値に関するサーバー情報によって知らされる可能性があり、リアクティブネゴシエーションにおける代替案のリストを調べることに似ています。

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

9.

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

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

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

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

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

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

                    

リンクされたハイパースキーマはAPIの基本URIを定義し、APIドキュメントへの「about」リンクと、これが基本URIのスキーマであることを示す「self」リンクの2つのリンクを提供します。この場合、基本URIはエントリポイントURIでもあります。

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

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

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

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

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

個々のものから始めて、システムに「もの」を追加しましょう。

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

私たちの「もの」にはサーバーが割り当てたIDがあり、「self」リンクを構築するために必要です。また、任意のタイプにすることができる「data」フィールドもあります。「definitions」セクションの理由は、次の例で明確になります。

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

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

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

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

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

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

「submissionSchema」と「submissionMediaType」フィールドは、ターゲットリソースの表現ではないペイロードを記述するためのものであり、"http(s)://" URIで使用する場合、HTTPの使用に関する付録 [HTTP]で示されているように、一般的にPOSTリクエストペイロードを参照します。

このケースでは、RFC 6068、セクション3 [RFC6068] に従い、「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-07-wip/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://api.example.com/stuff」から取得された次のインスタンスを考慮すると

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

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

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

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

追加または変更された入力はありません。
"mailto:[メールアドレス]?subject=The%20Awesome%20Thing"
"title"を"your work"に変更します。
"mailto:[メールアドレス]?subject=your%20work"
"title"を変更し、「cc」に"[メールアドレス]"を追加します。
"mailto:[メールアドレス]?subject=your%20work&[メールアドレス]"

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

リンクは、コンテキストリソースからターゲットリソースへの型付き接続です。古いリンクシリアライゼーションは、「rel」と同様にリンクリレーションタイプを受け取る「rev」キーワードをサポートしていますが、セマンティクスを反転します。これは長い間非推奨となっているため、JSON Hyper-Schemaはこれをサポートしません。「anchor」のコンテキストURIを変更する機能を使用して、リンクの方向を反転できます。また、どちらのリソースも現在のリソースではない2つのリソース間のリンクを記述するためにも使用できます。

例として、IANAに登録されている「up」リレーションがありますが、「down」はありません。HTTP Linkヘッダーでは、「"rev": "up"」として「down」を実装できます。

まず、HTTPでこれを行う方法を見てみましょう。「self」リンクと、セマンティック的に同一の2つのリンク(1つは「rev: "up"」、もう1つは「anchor」と「rel: "up"」を使用)を示します(フォーマットの制限により行が折り返されています)。

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

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

                    

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

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

    "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. コレクション

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

この例では、前のセクションで示した個々のシングルスキーマを再利用します。便宜上、ここに繰り返し記載されており、次に紹介するコレクションスキーマを指す「targetSchema」参照を持つ「collection」リンクが追加されています。

{
    "$id": "https://schema.example.com/thing",
    "$schema": "https://json-schema.dokyumento.jp/draft-07-wip/hyper-schema#",
    "base": "https://api.example.com",
    "type": "object",
    "required": ["data"],
    "properties": {
        "id": {"$ref": "#/definitions/id"},
        "data": true
    },
    "links": [
        {
            "rel": "self",
            "href": "things/{id}",
            "templateRequired": ["id"],
            "targetSchema": {"$ref": "#"}
        }, {
            "rel": "collection",
            "href": "/things",
            "targetSchema": {"$ref": "thing-collection#"},
            "submissionSchema": {"$ref": "#"}
        }
    ],
    "definitions": {
        "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-07-wip/hyper-schema#",
    "base": "https://api.example.com",
    "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"}
        }
    ]
}
                    
{
    "elements": [
        {"id": 12345, "data": {}},
        {"id": 67890, "data": {}}
    ]
}
                    

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

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

                    

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

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

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

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

関連するコレクションURIが1つしかないため、コレクションリンクは同一のターゲットURIを持ちます。完全な構築済みリンクセットの一部として両方のリンクを計算することが役に立たないように見えるかもしれませんが、必要に応じてリンクを構築する場合、この配置により、処理している「elements」エントリに関係なく、すぐに利用できる「collection」リンク定義が存在します。

9.5.1. ページネーション

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

{
    "properties": {
        "elements": {
            ...
        },
        "meta": {
            "type": "object",
            "properties": {
                "prev": {"$ref": "#/definitions/pagination"},
                "current": {"$ref": "#/definitions/pagination"},
                "next": {"$ref": "#/definitions/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": "#"}
        }
    ],
    "definitions": {
        "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://api.example.com/things",
        "contextPointer": "",
        "rel": "self",
        "targetUri":
            "https://api.example.com/things?offset=20,limit=2",
        "attachmentPointer": ""
    },
    {
        "contextUri": "https://api.example.com/things",
        "contextPointer": "",
        "rel": "next",
        "targetUri":
            "https://api.example.com/things?offset=22,limit=2",
        "attachmentPointer": ""
    }
]
                        

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

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

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

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

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

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

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

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

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

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

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

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

10.1. ターゲット属性

セクション6.5で述べたように、ターゲットリソースを記述するすべてのLDOキーワードは助言的であり、操作への応答でターゲットリソースによって提供される権威のある情報の代わりに使用してはなりません。ターゲットリソースの応答は、それ自身の権威のあるハイパー・スキーマを示す必要があります。

ターゲットレスポンスのハイパー・スキーマが("$id"によって)現在のLDOが見つかったハイパー・スキーマと一致する場合は、ターゲット属性を権威のあるものと見なすことができます。[CREF11]"$id"によるスプーフィングのリスクについて何かを追加する必要がありますが、仕様の他の部分がリンクされたスキーマを常に再ダウンロードすることを推奨していないため、リスク軽減オプションは不明です。

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

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

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

"targetHints"で伝えられるプロトコルメタデータの値は、権威のあるものとは見なしてはなりません。メタデータの値に関する誤った仮定に基づいて適用される可能性のあるプロトコルのセキュリティに関する考慮事項はすべて適用されます。

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

10.2. "self"リンク

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

11. 謝辞

JSONスキーマの初期ドラフトに取り組んでくださった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. 標準参考文献

[RFC2119] Bradner, S.、"RFCで要件レベルを示すために使用するキーワード"、BCP 14、RFC 2119、DOI 10.17487/RFC2119、1997年3月。
[RFC3986] Berners-Lee, T.Fielding, R.およびL. Masinter、"Uniform Resource Identifier (URI): Generic Syntax"、STD 66、RFC 3986、DOI 10.17487/RFC3986、2005年1月。
[RFC4287] Nottingham, M.およびR. Sayre、"The Atom Syndication Format"、RFC 4287、DOI 10.17487/RFC4287、2005年12月。
[RFC6570] Gregorio, J.Fielding, R.Hadley, M.Nottingham, M.およびD. Orchard、"URI Template"、RFC 6570、DOI 10.17487/RFC6570、2012年3月。
[RFC6573] Amundsen, M.、"The Item and Collection Link Relations"、RFC 6573、DOI 10.17487/RFC6573、2012年4月。
[RFC6901] Bryan, P.Zyp, K.およびM. Nottingham、"JavaScript Object Notation (JSON) Pointer"、RFC 6901、DOI 10.17487/RFC6901、2013年4月。
[RFC8288] Nottingham, M.、"Web Linking"、RFC 8288、DOI 10.17487/RFC8288、2017年10月。
[relative-json-pointer] Luff, G.およびH. Andrews、"Relative JSON Pointers"、Internet-Draft draft-handrews-relative-json-pointer-00、2017年11月。
[json-schema] Wright, A.およびH. Andrews、"JSON Schema: A Media Type for Describing JSON Documents"、Internet-Draft draft-handrews-json-schema-00、2017年11月。
[json-schema-validation] Wright, A.Andrews, H.およびG. Luff、"JSON Schema Validation: A Vocabulary for Structural Validation of JSON"、Internet-Draft draft-handrews-json-schema-validation-00、2017年11月。

12.2. 参考情報

[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、"The 'tag' URI Scheme"、RFC 4151、DOI 10.17487/RFC4151、2005年10月。
[RFC5789] Dusseault, L.およびJ. Snell、"PATCH Method for HTTP"、RFC 5789、DOI 10.17487/RFC5789、2010年3月。
[RFC6068] Duerst, M.Masinter, L.およびJ. Zawinski、"The 'mailto' URI Scheme"、RFC 6068、DOI 10.17487/RFC6068、2010年10月。
[RFC7230] Fielding, R.およびJ. Reschke、"Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing"、RFC 7230、DOI 10.17487/RFC7230、2014年6月。
[RFC7231] Fielding, R.およびJ. Reschke、"Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content"、RFC 7231、DOI 10.17487/RFC7231、2014年6月。
[RFC7807] Nottingham, M.およびE. Wilde、"Problem Details for HTTP APIs"、RFC 7807、DOI 10.17487/RFC7807、2016年3月。
[I-D.reschke-http-jfv] Reschke, J.、"A JSON Encoding for HTTP Header Field Values"、Internet-Draft draft-reschke-http-jfv-06、2017年6月。

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

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

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

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

A.1. ハイパー・スキーマを使用したリソースの進化

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

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

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

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

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

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

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

付録B. 変更ログ

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

draft-handrews-json-schema-hyperschema-00

draft-wright-json-schema-hyperschema-01

draft-wright-json-schema-hyperschema-00

draft-luff-json-hyper-schema-01

著者アドレス

Henry Andrews(編集者) Cloudflare, Inc. サンフランシスコカリフォルニア州 米国 メール:[email protected]
Austin Wright(編集者) メール:[email protected]