インターネット技術タスクフォース H. Andrews 編
インターネットドラフト Cloudflare, Inc.
意図されたステータス:情報提供 A. Wright 編
有効期限:2018年7月23日 2018年1月19日

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

概要

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年7月23日に期限切れになります。

著作権表示

Copyright (c) 2018 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. メタスキーマと出力スキーマ

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」テンプレート自体のアタッチメントポイントではなく、「base」テンプレートの解決を必要とする「href」または「anchor」キーワードのアタッチメントポイントであることに注意してください。

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"プロパティと類似しています。ユーザーエージェントは、リンクが実行される前にユーザーに提示するインターフェースを知らせるためにこの情報を使用してもよいですが、結果として得られるデータの解釈にはこの情報を使用してはなりません。代わりに、ユーザーエージェントは、実行時の解釈のためにレスポンスによって提供されたメディアタイプを使用しなければなりません。"targetMediaType"の誤用については、"セキュリティに関する懸念事項" [security]セクションで詳しく説明しています。

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

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

6.5.4. targetSchema

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

6.5.5. targetHints

[CREF1]このセクションは、その構造の大部分を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

[CREF2]"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 に制限されません。[CREF3]この記述は、例が最終的に配置される場所に移動される可能性があります。

6.6.4.2. submissionSchema

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

これは、「targetSchema[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つのハイパースキーマキーワードはURIテンプレート[RFC6570]です:「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」は、2つのうちどちらのプロセスを開始したかを示します(「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:
        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. リクエスト

ハイパーメディアスキーマの実装は、ターゲットリソースへの有効なリクエストを構築するために必要なすべての情報へのアクセスを提供する必要があります。

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

入力を受け入れる「hrefSchema」を含むターゲットURIの構築ルールは、すべてのリクエストで同一です。

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

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

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

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

7.5. レスポンス

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

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

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

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

設計時にすべての可能なレスポンスとそのスキーマを静的にマッピングすることは、JSONハイパーメディアスキーマの範囲外ですが、ハイパーメディアスキーマに基づいて構築される他のJSONスキーマボキャブラリ(付録A.3を参照)の範囲内にある可能性があります。

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

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

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

8. JSONハイパーメディアスキーマとHTTP

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

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

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

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

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

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

このセクションで説明されているように、各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ハイパーメディアスキーマは、ターゲットの表現を操作する代わりに、またはそれに加えて、任意のデータを処理するリソースを許可します。この任意のデータは、「submissionSchema」と「submissionMediaType」キーワードによって記述されます。HTTPの場合、POSTメソッドは、そのようなデータを処理する唯一のメソッドです。コレクションでPOSTを使用することについての特定の規約がありますが、POSTリクエストのセマンティクスは、HTTPではなく、ターゲットリソースによって定義されます。

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

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

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

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

HTTPレスポンスヘッダー情報のJSONシリアライゼーションは、進行中の作業「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機能のアドバタイジング

スキーマは、進行中の作業「HTTPヘッダーフィールド値のJSONエンコーディング」"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ハイパー・スキーマはHTTPコンテンツネゴシエーションを容易にし、プロアクティブ戦略とリアクティブ戦略のハイブリッドを可能にします。前述のように、ハイパー・スキーマには、「headerSchema」キーワードを使用して「Accept」、「Accept-Charset」、「Accept-Language」などのHTTPヘッダーのスキーマを含めることができます。ユーザーエージェントまたはクライアントアプリケーションは、このスキーマの情報(サポートされる言語の列挙リストなど)を使用して、リアクティブネゴシエーションプロセスを開始する最初のリクエストを行う代わりに使用できます。

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

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

9.

このセクションでは、URIとJSONポインターを構築するキーワードの使用方法を示します。結果は、テストスイートで使用される形式で表示されます。[CREF6]投稿してリンクする必要がありますが、現段階で内容を確認している皆様にとっては、かなり自明なはずです。

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

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

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

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/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/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テンプレートをインプットで解決する際にそれらを使用する方法について説明します。HTMLフォームとは異なり、HTMLフォームはURIを構築するかペイロードを送信するかのいずれかが必要ですが、同時に両方を許可しません。JSONハイパー・スキーマは、同じリンクに対する同じ操作の両方の種類の入力を記述できます。

「submissionSchema」と「submissionMediaType」フィールドは、ターゲットリソースの表現ではないペイロードを記述するためのもので、HTTP使用方法に関する付録 [HTTP]で示されているように、「http(s)://」URIで使用される場合、一般的に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/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"
タイトルを変更し、「cc」に「[email protected]」を追加します。
"mailto:[email protected]?subject=your%20work&[email protected]"

9.4. "アンカー"、"ベース"、およびURIテンプレート解決

リンクとは、コンテキストリソースからターゲットリソースへの型付き接続です。古いリンクシリアライゼーションは、「rel」と同様にリンクリレーションタイプを取る「rev」キーワードをサポートしていますが、セマンティクスを反転します。これは長い間非推奨となっているため、JSONハイパー・スキーマではサポートされていません。代わりに、「アンカー」のコンテキスト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」リンクのターゲットURIは「rel=self」リンクと同一であり、「anchor」(リンクのコンテキストを識別する)が子のURIに設定されていることに注意してください。「self」リンクも存在する場合、この種の反転リンクはツールで簡単に検出できます。

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

{
    "$id": "https://schema.example.com/tree-node",
    "$schema": "https://json-schema.dokyumento.jp/draft-07/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. コレクション

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

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

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

簡単な2要素のコレクションインスタンスを次に示します。

{
    "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の両方を考慮することが非常に重要です。

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

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

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

コレクションリンクは、関連するコレクション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」値により、この特定のインスタンスではリンクを使用できません。

[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#/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」キーワードを使用してアイテム作成操作を実行できます。[CREF8]コレクションがフィルタリングされておらず、ページングされていない場合、これは完璧に機能します。ただし、一般的に、作成されたリソースを含むコレクションにPOSTする必要があり、「self」リンクには、フィルター、ページング、その他のクエリパラメーターを含める必要があります。結果のアイテムがフィルターに一致しない場合、またはそのページに表示されない場合でも、このような「self」リンクにPOSTすることはまだ有効ですか?詳細については、GitHub issue #421を参照してください。 [CREF9]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が見つかったハイパー・スキーマと一致する場合、ターゲット属性を権威のあるものと見なすことができます。[CREF10]「$id」によるスプーフィングのリスクについて何かを追加する必要がありますが、仕様の他の部分ではリンクされたスキーマを常に再ダウンロードすることを推奨していないため、リスク軽減オプションは不明です。

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

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

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

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

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

10.2. "self" リンク

"self" のリンク関係がオブジェクトの完全な表現を示すために使用される場合、ターゲットURIが、"self" リンクを含むターゲットURIを含むリソース表現を要求するために使用されたURIと等価でないか、またはそのサブパスでない場合、ユーザーエージェントは、その表現をターゲットURIによって示されるリソースの権威的な表現とは見なすべきではありません。[CREF11]この段落で「サブパス」オプションによって意図されていたことが完全に明確ではなくなっています。「サブパス」オプションは、通常、そのコレクションのURIのサブパスであるターゲットURIを持つコレクション内の埋め込みアイテム表現の"self"リンクを、権威的なものと見なすことを許可することを意図していた可能性があります。しかし、これは単なる一般的な設計規則であり、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. 標準参照

[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」、インターネットドラフト draft-handrews-relative-json-pointer-01、2018年1月。
[json-schema] Wright, A.およびH. Andrews、「JSON Schema: A Media Type for Describing JSON Documents」、インターネットドラフト 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」、インターネットドラフト 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」、インターネットドラフト draft-reschke-http-jfv-06、2017年6月。

付録A. APIにおけるJSONハイパーSchemaの使用

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

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

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

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

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

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

A.2. 応答とエラー

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

A.3. APIのハイパーSchemaの静的解析

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

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

付録B. 変更ログ

[CREF13]インターネットドラフトの状態から外れる前に、このセクションを削除する必要があります。

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(編集者) Cloudflare, Inc. サンフランシスコカリフォルニア州 米国 メールアドレス: [メールアドレスは保護されています]
Austin Wright(編集者) メールアドレス: [メールアドレスは保護されています]