最新仕様 (v1.1)
ステータス
このページは、現在バージョン1.1であるJSON:APIの最新公開バージョンを示しています。JSON:APIの新しいバージョンは、削除せず、追加のみという戦略を用いて、常に下位互換性を維持します。追加事項は、当社のディスカッションフォーラムで提案できます。
仕様書本文に誤りを見つけた場合、または実装を作成した場合は、当社のGitHubリポジトリでissueまたはプルリクエストを作成して知らせてください。
はじめに
JSON:APIは、クライアントがリソースの取得または変更を要求する方法、およびサーバーがそれらの要求に応答する方法に関する仕様です。JSON:APIは、拡張機能とプロファイルで容易に拡張できます。
JSON:APIは、クライアントとサーバー間で転送されるリクエスト数とデータ量を最小限に抑えるように設計されています。この効率性は、可読性、柔軟性、検出可能性を損なうことなく実現されています。
JSON:APIでは、データ交換にJSON:APIメディアタイプ(application/vnd.api+json
)の使用が必要です。
セマンティクス
この仕様で定義されているすべてのドキュメントメンバー、クエリパラメータ、および処理ルールは、まとめて「仕様セマンティクス」と呼ばれます。
特定のドキュメントメンバー、クエリパラメータ、および処理ルールは、実装者が自由に定義するために予約されています。これらは「実装セマンティクス」と呼ばれます。
その他のセマンティクスはすべて、この仕様による将来の使用のために予約されています。
規約
このドキュメント内のキーワード「MUST」、「MUST NOT」、「REQUIRED」、「SHALL」、「SHALL NOT」、「SHOULD」、「SHOULD NOT」、「RECOMMENDED」、「NOT RECOMMENDED」、「MAY」、「OPTIONAL」は、BCP 14 [RFC2119] [RFC8174]に記載されているように、ここに示されているようにすべて大文字で表示される場合にのみ解釈されます。
JSON:APIメディアタイプ
JSON:APIメディアタイプはapplication/vnd.api+json
です。
メディアタイプパラメータ
JSON:API仕様では、拡張機能とプロファイルをそれぞれ指定するために使用されるext
とprofile
の2つのメディアタイプパラメータをサポートしています。
注:メディアタイプパラメータは、メディアタイプに付随できる追加の情報です。例えば、ヘッダー
Content-Type: text/html;charset="utf-8"
では、メディアタイプはtext/html
であり、charset
はパラメータです。
拡張機能
拡張機能は、追加の仕様セマンティクスを定義することで、基本仕様を「拡張」する手段を提供します。
拡張機能は、仕様セマンティクスを変更または削除したり、実装セマンティクスを指定したりすることはできません。
プロファイル
プロファイルは、実装間で仕様の特定の使用方法を共有するための手段を提供します。
プロファイルは実装セマンティクスを指定できますが、仕様セマンティクスを変更、追加、または削除することはできません。
メディアタイプパラメータのルール
JSON:APIメディアタイプは、ext
とprofile
以外のメディアタイプパラメータを指定してはなりません。ext
パラメータは拡張機能をサポートするために使用され、profile
パラメータはプロファイルをサポートするために使用されます。
拡張機能とプロファイルはそれぞれ、URIによって一意に識別されます。拡張機能またはプロファイルのURIにアクセスすると、その使用方法を説明するドキュメントが返されるはずです。ext
およびprofile
パラメータの値は、それぞれ、スペース区切り(U+0020 SPACE、「 」)の拡張機能またはプロファイルURIのリストと等しくなければなりません。
注:
ext
またはprofile
メディアタイプパラメータをシリアル化する際には、HTTP仕様では、パラメータ値を引用符(U+0022 QUOTATION MARK、「"」)で囲む必要があります。
拡張機能のルール
拡張機能は、追加の処理ルールまたはさらなる制限を課すことができ、下記のように新しいオブジェクトメンバーを定義できます。
拡張機能は、この仕様または他の拡張機能で定義されている処理ルール、制限、またはオブジェクトメンバーの要件を軽減または削除してはなりません。
拡張機能は、この仕様で定義されているドキュメント構造内に新しいメンバーを定義できます。拡張メンバー名のルールについては、下記で説明します。
拡張機能は、新しいクエリパラメータを定義できます。拡張機能で定義されたクエリパラメータのルールについては、下記で説明します。
拡張機能が新しいクエリパラメータまたはドキュメントメンバーを定義する場合、拡張機能は名前空間を定義して、拡張機能が現在のバージョンまたは将来のバージョンのこの仕様と競合しないようにする必要があります。名前空間は、次のすべての条件を満たす必要があります。
- 名前空間には、少なくとも1文字が含まれている必要があります。
- 名前空間には、次の文字のみが含まれている必要があります。
- U+0061~U+007A、「a-z」
- U+0041~U+005A、「A-Z」
- U+0030~U+0039、「0-9」
拡張機能は、複数の名前空間を定義してはなりません。すべてのクエリパラメータとドキュメントメンバーに使用される名前空間は、特定の拡張機能に対して同じでなければなりません。
次の例では、version
という名前空間を持つ拡張機能が、リソースごとのバージョン管理をサポートするためにversion:id
というリソースオブジェクトメンバーを指定しています。このメンバーは、次のように表示される場合があります。
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json;ext="https://jsonapi.dokyumento.jp/ext/version"
// ...
{
"type": "articles",
"id": "1",
"version:id": "42",
"attributes": {
"title": "Rails is Omakase"
}
}
// ...
プロファイルのルール
プロファイルの使用に関するルールは、RFC 6906によって規定されています。
プロファイルは、実装者に予約されているドキュメントメンバーと処理ルールを定義できます。
プロファイルは、実装固有のクエリパラメータ以外のクエリパラメータを定義してはなりません。
プロファイルは、この仕様または拡張機能によって定義されている処理ルールを変更または削除してはなりません。ただし、プロファイルは、実装者が自由に定義するために予約されているクエリパラメータの処理ルールを定義できます。
たとえば、プロファイルはfilter
クエリパラメータの解釈に関するルールを定義できますが、include
クエリパラメータのリレーションシップ名がドット区切りではなくスペース区切りであることを指定することはできません。
拡張機能とは異なり、プロファイルはドキュメントメンバーの名前空間を定義する必要はありません。プロファイルは仕様セマンティクスを定義できないため、現在または将来のバージョンのこの仕様と競合することはないからです。ただし、プロファイルが他のプロファイルと競合する可能性があります。したがって、実装者は、競合するプロファイルをサポートしないようにする責任があります。
次の例では、プロファイルがtimestamps
属性を定義しています。プロファイルによると、この属性はcreated
メンバーとmodified
メンバーを含むオブジェクトでなければならず、これらのメンバーの値はRFC 3339形式を使用する必要があります。このようなプロファイルが適用されると、応答は次のように表示される場合があります。
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json;profile="https://example.com/resource-timestamps"
// ...
{
"type": "articles",
"id": "1",
"attributes": {
"title": "Rails is Omakase",
"timestamps": {
"created": "2020-07-21T12:09:00Z",
"modified": "2020-07-30T10:19:01Z"
}
}
}
// ...
コンテンツネゴシエーション
普遍的な責任
クライアントとサーバーは、Content-Type
ヘッダーでJSON:APIメディアタイプを使用してすべてのJSON:APIペイロードを送信する必要があります。
クライアントとサーバーは、1つ以上の拡張機能をJSON:APIドキュメントに適用した場合、Content-Type
ヘッダーでext
メディアタイプパラメータを指定する必要があります。
クライアントとサーバーは、1つ以上のプロファイルをJSON:APIドキュメントに適用した場合、Content-Type
ヘッダーでprofile
メディアタイプパラメータを指定する必要があります。
クライアントの責任
JSON:APIレスポンスドキュメントを処理する場合、クライアントは、サーバーのContent-Type
ヘッダーにあるext
とprofile
パラメータ以外のすべてのパラメータを無視する必要があります。
クライアントは、Accept
ヘッダーでext
メディアタイプパラメータを使用して、サーバーが指定されたすべての拡張機能をレスポンスドキュメントに適用することを要求できます。
クライアントは、Accept
ヘッダーでprofile
メディアタイプパラメータを使用して、サーバーが1つ以上のプロファイルをレスポンスドキュメントに適用することを要求できます。
注:クライアントは、
Accept
ヘッダーで複数の許容可能なメディアタイプを送信できます。これには、JSON:APIメディアタイプの複数のインスタンスも含まれます。これにより、クライアントはext
およびprofile
メディアタイプパラメータのさまざまな組み合わせを要求できます。クライアントは、品質値を使用して、特定の組み合わせが他の組み合わせよりも優先度が低いことを示すことができます。q値を指定せずに指定されたメディアタイプは、その順序に関係なく、互いに優先度が等しく、常にq値が1未満のメディアタイプよりも優先されます。
サーバーの役割
リクエストがContent-Type
ヘッダーにJSON:APIメディアタイプを指定している場合、そのメディアタイプにext
またはprofile
以外のメディアタイプパラメータが含まれているなら、サーバーは415 Unsupported Media Type
ステータスコードで応答**しなければならない**。
リクエストがContent-Type
ヘッダーにext
メディアタイプパラメータで変更されたJSON:APIメディアタイプのインスタンスを指定し、そのパラメータがサポートされていない拡張URIを含んでいる場合、サーバーは415 Unsupported Media Type
ステータスコードで応答**しなければならない**。
注記: この仕様のバージョン1.1をサポートしていないJSON:APIサーバーは、
ext
またはprofile
メディアタイプパラメータが存在する場合、415 Unsupported Media Type
クライアントエラーで応答する。
リクエストのAccept
ヘッダーにJSON:APIメディアタイプのインスタンスが含まれている場合、サーバーはext
またはprofile
以外のメディアタイプパラメータで変更されたそのメディアタイプのインスタンスを無視**しなければならない**。ext
またはprofile
以外のメディアタイプパラメータで変更されたインスタンスのみが存在する場合、サーバーは406 Not Acceptable
ステータスコードで応答**しなければならない**。ext
パラメータで変更され、それぞれが少なくとも1つのサポートされていない拡張URIを含むそのメディアタイプのすべてのインスタンスの場合も、サーバーは406 Not Acceptable
で応答**しなければならない**。
profile
パラメータを受け取った場合、サーバーは要求されたプロファイル(複数可)を応答に適用するよう**試みるべき**である。サーバーは認識できないプロファイルはすべて無視**しなければならない**。
注記: 上記のルールは、クライアントとサーバー間の拡張機能に関する厳格な合意を保証する一方、プロファイルの適用はサーバーの裁量に任されている。
ext
またはprofile
メディアタイプパラメータをサポートするサーバーは、Vary
ヘッダーにAccept
を値の1つとして指定する**べき**である。これは、プロファイルや拡張機能が適用された応答と適用されていない応答の両方に適用される。profiles extensions
注記: 一部のHTTP仲介者(例:CDN)は、特にそれを尊重するように設定されていない限り、
Vary
ヘッダーを無視することがある。
ドキュメント構造
このセクションでは、JSON:APIメディアタイプによって識別されるJSON:APIドキュメントの構造について説明する。JSON:APIドキュメントは、JavaScript Object Notation (JSON) [RFC8259]で定義されている。
リクエストドキュメントとレスポンスドキュメントの両方で同じメディアタイプが使用されるが、特定の側面は一方のみに適用される。これらの違いについては以下で説明する。
拡張機能は、ドキュメント構造内に新しいメンバーを定義する**ことができる**。これらのメンバーは、以下に指定されている命名要件に準拠**しなければならない**。
特に明記されていない限り、この仕様または適用された拡張機能によって定義されたオブジェクトには、追加のメンバーを含んでは**ならない**。クライアントとサーバーの実装は、非準拠のメンバーを無視**しなければならない**。
注記: これらの条件により、この仕様は追加的な変更を通じて進化できる。
トップレベル
データを含むすべてのJSON:APIリクエストおよびレスポンスドキュメントのルートには、JSONオブジェクトが**存在しなければならない**。このオブジェクトはドキュメントの「トップレベル」を定義する。
ドキュメントには、次のトップレベルメンバーのうち少なくとも1つが含まれてい**なければならない**
data
とerrors
のメンバーは、同じドキュメントに同時に存在しては**ならない**。
ドキュメントには、次のトップレベルメンバーのいずれかを含める**ことができる**
jsonapi
: サーバーの実装について説明するオブジェクト。links
: ドキュメント全体に関連するリンクオブジェクト。included
: プライマリデータおよび/または互いに関連するリソースオブジェクトの配列(「含まれるリソース」)。
ドキュメントにトップレベルのdata
キーが含まれていない場合、included
メンバーも存在しては**ならない**。
トップレベルのリンクオブジェクトには、次のメンバーを含める**ことができる**
self
: 現在のレスポンスドキュメントを生成したリンク。ドキュメントに拡張機能またはプロファイルが適用されている場合、このリンクは、type
ターゲット属性に適用可能なすべてのパラメータを含むJSON:APIメディアタイプを指定するリンクオブジェクトで表される**べき**である。related
: プライマリデータがリソース関係を表す場合の関連リソースリンク。describedby
: 現在のドキュメントの説明ドキュメント(例:OpenAPIまたはJSON Schema)へのリンク。- プライマリデータのページネーションリンク。
注記: トップレベルの
links
オブジェクト内のself
リンクにより、クライアントは現在のレスポンスドキュメントによって表されるデータを更新できる。クライアントは、追加情報を適用せずに提供されたリンクを使用できる必要がある。したがって、リンクには、レスポンスドキュメントを生成するためにクライアントによって提供されたクエリパラメータが含まれている必要がある。これには、[関連リソースの包含][fetching resources]、[スパースフィールドセット][fetching sparse fieldsets]、[ソート][fetching sorting]、[ページネーション][fetching pagination]、[フィルタリング][fetching filtering]に使用されるクエリパラメータが含まれるが、これらに限定されない。
ドキュメントの「プライマリデータ」は、リクエストの対象となるリソースまたはリソースのコレクションの表現である。
プライマリデータは、次のいずれかで**なければならない**
- 単一のリソースを対象とするリクエストの場合は、単一のリソースオブジェクト、単一のリソース識別子オブジェクト、または
null
。 - リソースコレクションを対象とするリクエストの場合は、リソースオブジェクトの配列、リソース識別子オブジェクトの配列、または空の配列(
[]
)。
たとえば、次のプライマリデータは単一のリソースオブジェクトである。
{
"data": {
"type": "articles",
"id": "1",
"attributes": {
// ... this article's attributes
},
"relationships": {
// ... this article's relationships
}
}
}
次のプライマリデータは、同じリソースを参照する単一のリソース識別子オブジェクトである。
{
"data": {
"type": "articles",
"id": "1"
}
}
論理的なリソースのコレクションは、1つのアイテムしか含まれていない場合や空の場合でも、配列として表され**なければならない**。
リソースオブジェクト
「リソースオブジェクト」は、リソースを表すためにJSON:APIドキュメントに表示される。
リソースオブジェクトには、少なくとも次のトップレベルメンバーが含まれてい**なければならない**
id
type
例外: リソースオブジェクトがクライアントに由来し、サーバーで作成される新しいリソースを表す場合、id
メンバーは必須ではない。その場合、クライアントはlid
メンバーを含めて、ドキュメント内でtype
によってリソースを一意にローカルに識別することができる。
さらに、リソースオブジェクトには、次のトップレベルメンバーのいずれかを含める**ことができる**
attributes
: リソースのデータの一部を表す属性オブジェクト。relationships
: リソースと他のJSON:APIリソース間の関係を記述する関係オブジェクト。links
: リソースに関連するリンクを含むリンクオブジェクト。meta
: 属性または関係として表すことができないリソースに関する標準外のメタ情報を含むメタオブジェクト。
記事(つまり、「記事」というタイプの資源)がドキュメントにどのように表示されるかを示す例を以下に示す。
// ...
{
"type": "articles",
"id": "1",
"attributes": {
"title": "Rails is Omakase"
},
"relationships": {
"author": {
"links": {
"self": "/articles/1/relationships/author",
"related": "/articles/1/author"
},
"data": { "type": "people", "id": "9" }
}
}
}
// ...
識別
上記のように、すべてのリソースオブジェクトにはtype
メンバーが含まれてい**なければならない**。すべてのリソースオブジェクトにはid
メンバーも含まれてい**なければならない**。ただし、リソースオブジェクトがクライアントに由来し、サーバーで作成される新しいリソースを表す場合を除く。この例外によりid
が省略された場合、lid
メンバーを含めて、ドキュメント内でtype
によってリソースを一意にローカルに識別することができる。lid
メンバーの値は、ドキュメント内のリソースのすべての表現(リソース識別子オブジェクトを含む)で同一で**なければならない**。
id
、type
、およびlid
メンバーの値は、文字列で**なければならない**。
特定のAPI内では、各リソースオブジェクトのtype
とid
のペアは、単一で一意のリソースを識別する**必要がある**。(サーバー、または1つとして機能する複数のサーバーによって制御されるURIのセットがAPIを構成する。)
type
メンバーは、共通の属性と関係を共有するリソースオブジェクトを記述するために使用される。
type
メンバーの値は、メンバー名と同じ制約に従わ**なければならない**。
注記: この仕様は屈折ルールに無関係であるため、
type
の値は複数形でも単数形でもかまわない。ただし、実装全体で同じ値を常に使用する必要がある。
フィールド
リソースオブジェクトの属性と関係は、まとめてその「フィールド」と呼ばれる。
リソースオブジェクトのフィールドは、互いおよびtype
とid
と共通の名前空間を共有する**必要がある**。言い換えれば、リソースは同じ名前の属性と関係を持つことはできず、type
またはid
という名前の属性または関係を持つこともできない。
属性
attributes
キーの値は**必ず**オブジェクト(「attributesオブジェクト」)である必要があります。attributesオブジェクトのメンバ(「attributes」)は、それが定義されているリソースオブジェクトに関する情報を表します。
attributesには、JSONオブジェクトや配列を含む複雑なデータ構造を含む、任意の有効なJSON値を含めることができます。
関連リソースを参照するキー(例:author_id
)は、**属性として現れてはなりません**。代わりに、リレーションシップを**使用する必要があります**。
リレーションシップ
relationships
キーの値は**必ず**オブジェクト(「relationshipsオブジェクト」)である必要があります。relationshipsオブジェクトの各メンバは、それが定義されているリソースオブジェクトから他のリソースオブジェクトへの「リレーションシップ」を表します。
リレーションシップは、一対一または多対一にすることができます。
リレーションシップの名前はそのキーで指定されます。そのキーの値は**必ず**オブジェクト(「リレーションシップオブジェクト」)である必要があります。
「リレーションシップオブジェクト」は、以下の少なくとも1つを含んでいる**必要があります**
links
:以下の少なくとも1つを含むlinksオブジェクトself
:リレーションシップ自体のリンク(「リレーションシップリンク」)。このリンクにより、クライアントはリレーションシップを直接操作できます。たとえば、article
のリレーションシップURLを通じてauthor
を削除すると、people
リソース自体を削除することなく、その人物をarticle
から切り離すことができます。正常にフェッチされた場合、このリンクは関連リソースのリンケージをその主要なデータとして返します。(リレーションシップのフェッチを参照してください。)related
:関連リソースリンク- 適用された拡張機能によって定義されたメンバー。
data
:リソースリンケージmeta
:リレーションシップに関する非標準のメタ情報を含むmetaオブジェクト- 適用された拡張機能によって定義されたメンバー。
多対一のリレーションシップを表すリレーションシップオブジェクトは、以下に説明するlinks
メンバの下にページングリンクを含めることもできます。リレーションシップオブジェクト内のページングリンクは、関連リソースではなく、リレーションシップデータをページングする**必要があります**。
関連リソースリンク
「関連リソースリンク」は、リレーションシップでリンクされているリソースオブジェクトへのアクセスを提供します。フェッチされると、関連リソースオブジェクトがレスポンスの主要なデータとして返されます。
たとえば、article
のcomments
リレーションシップは、GET
リクエストを通じて取得されたときに、コメントリソースオブジェクトのコレクションを返すリンクを指定できます。
存在する場合、関連リソースリンクは、リレーションシップが現在ターゲットリソースに関連付けられていなくても、有効なURLを参照する**必要があります**。さらに、関連リソースリンクは、そのリレーションシップの内容が変更されたために変更されることは**ありません**。
リソースリンケージ
複合ドキュメントのリソースリンケージにより、クライアントはリンクを介してURLをGET
することなく、含まれているすべてのリソースオブジェクトをリンクできます。
リソースリンケージは、以下のいずれかとして表される**必要があります**
- 空の一対一のリレーションシップの場合は
null
。 - 空の多対一のリレーションシップの場合は空の配列(
[]
)。 - 空でない一対一のリレーションシップの場合は、単一のリソース識別子オブジェクト。
- 空でない多対一のリレーションシップの場合は、リソース識別子オブジェクトの配列。
注:仕様では、多対一のリレーションシップのリンケージ配列内のリソース識別子オブジェクトの順序に意味はありませんが、実装ではそのようにすることがあります。リソース識別子オブジェクトの配列は、順序付きまたは順序なしのリレーションシップを表すことができ、両方のタイプを1つのレスポンスオブジェクトに混在させることができます。
たとえば、次の記事はauthor
に関連付けられています。
// ...
{
"type": "articles",
"id": "1",
"attributes": {
"title": "Rails is Omakase"
},
"relationships": {
"author": {
"links": {
"self": "http://example.com/articles/1/relationships/author",
"related": "http://example.com/articles/1/author"
},
"data": { "type": "people", "id": "9" }
}
},
"links": {
"self": "http://example.com/articles/1"
}
}
// ...
author
リレーションシップには、リレーションシップ自体のリンク(クライアントが関連するauthorを直接変更できるようにする)、リソースオブジェクトをフェッチするための関連リソースリンク、およびリンケージ情報が含まれています。
リソースリンク
各リソースオブジェクト内のオプションのlinks
メンバには、リソースに関連するリンクが含まれています。
存在する場合、このlinksオブジェクトは、リソースオブジェクトによって表されるリソースを識別するself
リンクを含めることができます。
// ...
{
"type": "articles",
"id": "1",
"attributes": {
"title": "Rails is Omakase"
},
"links": {
"self": "http://example.com/articles/1"
}
}
// ...
サーバは、指定されたURLへのGET
リクエストに、リソースを主要なデータとして含むレスポンスで応答する**必要があります**。
リソース識別子オブジェクト
「リソース識別子オブジェクト」は、個々のリソースを識別するオブジェクトです。
「リソース識別子オブジェクト」は、type
メンバを含んでいる**必要があります**。また、サーバで作成される新しいリソースを表す場合を除き、id
メンバを含んでいる**必要があります**。この場合、新しいリソースを識別するlid
メンバを含める**必要があります**。
id
、type
、およびlid
メンバーの値は、文字列で**なければならない**。
「リソース識別子オブジェクト」は、非標準のメタ情報を含むmetaオブジェクトである値を持つmeta
メンバを含めることもできます。
複合ドキュメント
サーバは、要求された主要なリソースとともに関連リソースを含むレスポンスを許可することができます。このようなレスポンスは「複合ドキュメント」と呼ばれます。
複合ドキュメントでは、含まれるすべてのリソースは、最上位のincluded
メンバ内のリソースオブジェクトの配列として表される**必要があります**。
含まれるすべてのリソースオブジェクトは、ドキュメントの主要なデータから始まるリレーションシップのチェーンを介して識別される**必要があります**。つまり、複合ドキュメントには「完全なリンケージ」が必要であり、ドキュメントの主要なデータとの直接的または間接的なリレーションシップがないリソースオブジェクトを含めることはできません。
完全なリンケージ要件の唯一の例外は、クライアントによって要求されたスパースフィールドセットのために、リンケージデータを含むはずのリレーションシップフィールドが除外されている場合です。
複数の含まれるリレーションシップを持つ完全なドキュメントの例
{
"data": [{
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON:API paints my bikeshed!"
},
"links": {
"self": "http://example.com/articles/1"
},
"relationships": {
"author": {
"links": {
"self": "http://example.com/articles/1/relationships/author",
"related": "http://example.com/articles/1/author"
},
"data": { "type": "people", "id": "9" }
},
"comments": {
"links": {
"self": "http://example.com/articles/1/relationships/comments",
"related": "http://example.com/articles/1/comments"
},
"data": [
{ "type": "comments", "id": "5" },
{ "type": "comments", "id": "12" }
]
}
}
}],
"included": [{
"type": "people",
"id": "9",
"attributes": {
"firstName": "Dan",
"lastName": "Gebhardt",
"twitter": "dgeb"
},
"links": {
"self": "http://example.com/people/9"
}
}, {
"type": "comments",
"id": "5",
"attributes": {
"body": "First!"
},
"relationships": {
"author": {
"data": { "type": "people", "id": "2" }
}
},
"links": {
"self": "http://example.com/comments/5"
}
}, {
"type": "comments",
"id": "12",
"attributes": {
"body": "I like XML better"
},
"relationships": {
"author": {
"data": { "type": "people", "id": "9" }
}
},
"links": {
"self": "http://example.com/comments/12"
}
}]
}
複合ドキュメントは、各type
とid
ペアに対して、複数のリソースオブジェクトを含めることは**できません**。
注:単一のドキュメントでは、
type
とid
を複合キーとして考え、ドキュメントの別の部分にあるリソースオブジェクトを一意に参照することができます。
注:
id
メンバを含まないがlid
を含むリソースの場合、lid
はリソースの同一性を確立し、ドキュメント全体のリソースオブジェクトとリソース識別子オブジェクト間のリンケージを確立するのに十分です。
注:このアプローチにより、同じリソースが複数回参照されていても、各レスポンスで単一の標準的なリソースオブジェクトが返されることが保証されます。
メタ情報
指定されている場合、meta
メンバを使用して非標準のメタ情報を含めることができます。各meta
メンバの値は**必ず**オブジェクト(「metaオブジェクト」)である必要があります。
任意のメンバをmeta
オブジェクト内に指定できます。
例:
{
"meta": {
"copyright": "Copyright 2015 Example Corp.",
"authors": [
"Yehuda Katz",
"Steve Klabnik",
"Dan Gebhardt",
"Tyler Kellen"
]
},
"data": {
// ...
}
}
リンク
指定されている場合、links
メンバを使用してリンクを表すことができます。このメンバの値は**必ず**オブジェクト(「linksオブジェクト」)である必要があります。
このオブジェクト内では、リンクは次のいずれかとして表される**必要があります**。
- リンクのターゲットを指すURI参照[RFC3986セクション4.1]である文字列。
- リンクオブジェクト。
- リンクが存在しない場合は
null
。
リンクのリレーションタイプは、リンクがリンクオブジェクトであり、リンクオブジェクトにrel
メンバがある場合を除き、リンクの名前から推測する**必要があります**。
リンクのコンテキストは、それが表示される最上位オブジェクト、リソースオブジェクト、またはリレーションシップオブジェクトです。
以下の例では、self
リンクは文字列ですが、related
リンクはリンクオブジェクトです。related
リンクオブジェクトは、ターゲットとなる関連リソースコレクションに関する追加情報と、そのコレクションの説明ドキュメントとして機能するスキーマを提供します。
"links": {
"self": "http://example.com/articles/1/relationships/comments",
"related": {
"href": "http://example.com/articles/1/comments",
"title": "Comments",
"describedby": "http://example.com/schemas/article-comments",
"meta": {
"count": 10
}
}
}
リンクオブジェクト
「リンクオブジェクト」は、ウェブリンクを表すオブジェクトです。
リンクオブジェクトは、次のメンバを含んでいる**必要があります**
href
:リンクのターゲットを指すURI参照[RFC3986セクション4.1]である文字列。
リンクオブジェクトは、次のメンバを含めることもできます。
rel
:リンクのリレーションタイプを示す文字列。この文字列は、有効なリンクリレーションタイプである**必要があります**。describedby
: リンク先の記述ドキュメント(例:OpenAPIまたはJSON Schema)へのリンク。title
: リンク先のラベルとして機能する文字列。人間が読み取れる識別子(例:メニュー項目)として使用できます。type
: リンク先のメディアタイプを示す文字列。hreflang
: リンク先の言語を示す文字列または文字列の配列。文字列の配列は、リンク先が複数の言語で使用できることを示します。各文字列は、有効な言語タグ[RFC5646]である**必要があります**。meta
: リンクに関する非標準のメタ情報を格納するメタオブジェクト。
注:
type
とhreflang
メンバはヒントに過ぎません。リンクが実際にたどられた場合、ターゲットリソースが指定されたメディアタイプまたは言語で使用できるとは限りません。
JSON:APIオブジェクト
JSON:APIドキュメントには、最上位レベルのjsonapi
メンバの下にその実装に関する情報を含めることができます。存在する場合、jsonapi
メンバの値はオブジェクト(「jsonapiオブジェクト」)である**必要があります**。
jsonapiオブジェクトには、次のメンバを含めることができます。
version
- サポートされる最高のJSON:APIバージョンを示す文字列。ext
- 適用されたすべての拡張機能のURIの配列。profile
- 適用されたすべてのプロファイルのURIの配列。meta
- 非標準のメタ情報を格納するメタオブジェクト。
クライアントとサーバーは、コンテンツネゴシエーションにext
またはprofile
メンバを使用しては**なりません**。コンテンツネゴシエーションは、Content-Type
ヘッダーのメディアタイプパラメーターに基づいてのみ行う**必要があります**。
簡単な例を以下に示します。
{
"jsonapi": {
"version": "1.1",
"ext": [
"https://jsonapi.dokyumento.jp/ext/atomic"
],
"profile": [
"http://example.com/profiles/flexible-pagination",
"http://example.com/profiles/resource-versioning"
]
}
}
version
メンバが存在しない場合、クライアントはサーバーが仕様のバージョン1.0以上を実装していると想定する必要があります。
注:JSON:APIは追加的な変更のみを行うことを約束しているため、バージョン文字列は主にサーバーがサポートする可能性のある新しい機能を示しています。
メンバー名
JSON:APIドキュメントで使用される実装およびプロファイルで定義されたメンバー名は、クライアントとサーバーによって大文字と小文字が区別され、次のすべての条件を満たす**必要があります**。
- メンバー名は、少なくとも1文字を含む**必要があります**。
- メンバー名は、以下に示す許可された文字のみを含む**必要があります**。
- メンバー名は、以下で定義されているように、「グローバルに許可される文字」で開始および終了する**必要があります**。
メンバー名をURLに簡単にマッピングできるようにするために、RFC 3986で指定されている予約されていないURLセーフな文字のみを使用することを**推奨**します。
許可された文字
次の「グローバルに許可される文字」は、メンバー名のどこにでも使用できます。
- U+0061~U+007A、「a-z」
- U+0041~U+005A、「A-Z」
- U+0030~U+0039、「0-9」
- U+0080以上(非ASCII Unicode文字。*推奨されません、URLセーフではありません*)
さらに、次の文字は、最初の文字または最後の文字を除いて、メンバー名で使用できます。
- U+002D ハイフンマイナス、"-"
- U+005F 下線、"_"
- U+0020 スペース、" " *(推奨されません、URLセーフではありません)*
予約済み文字
次の文字は、実装およびプロファイルで定義されたメンバー名で使用しては**なりません**。
- U+002B プラス記号、"+" *(URLクエリ文字列で意味がオーバーロードされています)*
- U+002C カンマ、"," *(リレーションシップパスのセパレータとして使用されます)*
- U+002E ピリオド、"." *(リレーションシップパス内でセパレータとして使用されます)*
- U+005B 左角括弧、"[" *(クエリパラメータファミリで使用されます)*
- U+005D 右角括弧、"]" *(クエリパラメータファミリで使用されます)*
- U+0021 感嘆符、"!"
- U+0022 クォーテーションマーク、'"'
- U+0023 シャープ記号、"#"
- U+0024 ドル記号、"$"
- U+0025 パーセント記号、"%"
- U+0026 アンパサンド、"&"
- U+0027 アポストロフィ、"'"
- U+0028 左括弧、"("
- U+0029 右括弧、")"
- U+002A アスタリスク、"*"
- U+002F ソリダス、"/"
- U+003A コロン、":"
- U+003B セミコロン、";"
- U+003C 小なり記号、"<"
- U+003D 等号、"="
- U+003E 大なり記号、">"
- U+003F クエスチョンマーク、"?"
- U+0040 アットマーク、"@" (@-メンバーの最初の文字を除く)
- U+005C バックスラッシュ、"\"
- U+005E キャレット、"^"
- U+0060 バッククォート、"`"
- U+007B 左中括弧、"{"
- U+007C 縦線、"|"
- U+007D 右中括弧、"}"
- U+007E チルダ、"~"
- U+007F DELETE
- U+0000~U+001F(C0制御文字)
@-メンバー
メンバー名は、アットマーク(U+0040 アットマーク、"@")で始まることもできます。このように名前が付けられたメンバーは「@-メンバー」と呼ばれます。@-メンバーは、ドキュメントのどこにでも表示される場合があります。
この仕様では、@-メンバーの意味や使用方法に関するガイダンスは提供されていません。@-メンバーは実装セマンティクスと見なされます。このサブセクション以外で与えられたこの仕様の定義と処理命令を解釈する際には、@-メンバーを無視する**必要があります**。たとえば、属性は上記で属性オブジェクトの任意のメンバーとして定義されています。ただし、その定義を解釈する際には@-メンバーを無視する必要があるため、属性オブジェクトに存在する@-メンバーは属性ではありません。
注:「@」メンバーは、JSON:APIドキュメントにJSON-LDデータを追加するために使用できます。そのようなドキュメントは、JSON-LDクライアントにJSON-LDデータが含まれていることを伝えるために、追加のヘッダーで提供する必要があります。
拡張メンバー
拡張機能によって導入された新しいメンバーの名前は、拡張機能の名前空間にコロン(:
)を付けて接頭辞を付ける**必要があります**。名前の残りの部分は、実装で定義されたメンバー名のルールに従う**必要があります**。
データの取得
リソースやリレーションシップを含むデータは、エンドポイントにGET
リクエストを送信することで取得できます。
レスポンスは、以下に説明するオプション機能を使用してさらに絞り込むことができます。
リソースの取得
サーバーは、次のように提供されるすべてのURLのリソースデータの取得をサポートする**必要があります**。
- 最上位レベルのリンクオブジェクトの一部である
self
リンク - リソースレベルのリンクオブジェクトの一部である
self
リンク - リレーションシップレベルのリンクオブジェクトの一部である
related
リンク
たとえば、次のリクエストは記事のコレクションを取得します。
GET /articles HTTP/1.1
Accept: application/vnd.api+json
次のリクエストは記事を取得します。
GET /articles/1 HTTP/1.1
Accept: application/vnd.api+json
そして、次のリクエストは記事の著者を取得します。
GET /articles/1/author HTTP/1.1
Accept: application/vnd.api+json
レスポンス
200 OK
サーバーは、個々のリソースまたはリソースコレクションを取得するための成功したリクエストに対して、200 OK
レスポンスで応答する**必要があります**。
サーバーは、リソースコレクションの取得を成功したリクエストに対して、リソースオブジェクトの配列、または空の配列([]
)をレスポンスドキュメントのプライマリデータとして応答する**必要があります**。
たとえば、記事のコレクションへのGET
リクエストは、次を返す可能性があります。
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "http://example.com/articles"
},
"data": [{
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON:API paints my bikeshed!"
}
}, {
"type": "articles",
"id": "2",
"attributes": {
"title": "Rails is Omakase"
}
}]
}
空のコレクションを表す同様のレスポンスは次のようになります。
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "http://example.com/articles"
},
"data": []
}
サーバーは、個々のリソースの取得を成功したリクエストに対して、リソースオブジェクトまたはnull
をレスポンスドキュメントのプライマリデータとして提供する**必要があります**。
null
は、リクエストされたURLが単一のリソースに対応する可能性があるが、現在対応していない場合にのみ適切なレスポンスです。
注:たとえば、1対1のリレーションシップリンクに関連するリソースを取得するリクエストを考えてみましょう。このリクエストは、リレーションシップが空の場合(リンクがリソースに対応していない場合)、
null
で応答しますが、それ以外の場合は単一の関連リソースのリソースオブジェクトで応答します。
たとえば、個々の記事へのGET
リクエストは、次を返す可能性があります。
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "http://example.com/articles/1"
},
"data": {
"type": "articles",
"id": "1",
"attributes": {
"title": "JSON:API paints my bikeshed!"
},
"relationships": {
"author": {
"links": {
"related": "http://example.com/articles/1/author"
}
}
}
}
}
上記の記事の著者が存在しない場合、その関連リソースへのGET
リクエストは次を返します。
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "http://example.com/articles/1/author"
},
"data": null
}
404 Not Found
サーバーは、存在しない単一のリソースを取得するリクエストを処理する場合、null
をプライマリデータとして200 OK
レスポンスが保証される場合を除き、404 Not Found
で応答する**必要があります**(上記で説明)。
その他のレスポンス
サーバーは、その他のHTTPステータスコードで応答できます。
サーバーは、エラーレスポンスにエラーの詳細を含めることができます。
サーバーはHTTPセマンティクス
に従ってレスポンスを準備する必要があり、クライアントはレスポンスを解釈する必要があります。
リレーションシップの取得
サーバーは、リレーションシップのlinks
オブジェクトの一部であるself
リンクとして提供されるすべてのリレーションシップURLのリレーションシップデータの取得をサポートする**必要があります**。
たとえば、次のリクエストは記事のコメントに関するデータを取得します。
GET /articles/1/relationships/comments HTTP/1.1
Accept: application/vnd.api+json
そして、次のリクエストは記事の著者に関するデータを取得します。
GET /articles/1/relationships/author HTTP/1.1
Accept: application/vnd.api+json
レスポンス
200 OK
サーバーは、リレーションシップを取得するための成功したリクエストに対して、200 OK
レスポンスで応答する**必要があります**。
レスポンスドキュメントのプライマリデータは、リレーションシップオブジェクトについて上記で説明されているように、リソースリンケージの適切な値と一致する**必要があります**。
最上位レベルのリンクオブジェクトには、リレーションシップオブジェクトについて上記で説明されているように、self
リンクとrelated
リンクを含めることができます。
たとえば、1対1のリレーションシップリンクからのURLへのGET
リクエストは、次を返す可能性があります。
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "/articles/1/relationships/author",
"related": "/articles/1/author"
},
"data": {
"type": "people",
"id": "12"
}
}
上記のリレーションシップが空の場合、同じURLへのGET
リクエストは次を返します。
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "/articles/1/relationships/author",
"related": "/articles/1/author"
},
"data": null
}
1対多のリレーションシップリンクからのURLへのGET
リクエストは、次を返す可能性があります。
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "/articles/1/relationships/tags",
"related": "/articles/1/tags"
},
"data": [
{ "type": "tags", "id": "2" },
{ "type": "tags", "id": "3" }
]
}
上記のリレーションシップが空の場合、同じURLへのGET
リクエストは次を返します。
HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
{
"links": {
"self": "/articles/1/relationships/tags",
"related": "/articles/1/tags"
},
"data": []
}
404 Not Found
関係リンクのURLを取得するリクエストを処理する際に、サーバーは存在しないURLの場合、404 Not Found
を返さなければならない。
注記: これは、関係を持つ親リソースが存在しない場合に発生する可能性があります。例えば、
/articles/1
が存在しない場合、/articles/1/relationships/tags
へのリクエストは404 Not Found
を返します。
関係リンクのURLが存在するが、関係が空の場合、上記のように200 OK
を返さなければならない。
その他のレスポンス
サーバーは、その他のHTTPステータスコードで応答できます。
サーバーは、エラーレスポンスにエラーの詳細を含めることができます。
サーバーはHTTPセマンティクス
に従ってレスポンスを準備する必要があり、クライアントはレスポンスを解釈する必要があります。
関連リソースの包含
エンドポイントは、デフォルトで主要データに関連するリソースを返すことができる。
エンドポイントは、include
クエリパラメータをサポートして、クライアントが返す関連リソースをカスタマイズできるようにすることもできる。
エンドポイントがinclude
パラメータをサポートしていない場合、それを含むリクエストには400 Bad Request
で応答しなければならない。
エンドポイントがinclude
パラメータをサポートしており、クライアントがそれを指定した場合
- サーバーのレスポンスは、
included
キーを持つ複合ドキュメントでなければならない。included
キーが空の配列を持つ場合でも同様である(要求された関係が空であるため)。 - サーバーは、複合ドキュメントの
included
セクションに、要求されていないリソースオブジェクトを含めてはならない。
include
パラメータの値は、コンマ区切り(U+002C COMMA、「、」)の関係パスのリストでなければならない。関係パスとは、ドット区切り(U+002E FULL-STOP、「.」)の関係名のリストである。空の値は、関連リソースを返さないことを示す。
サーバーが関係パスを識別できない場合、またはパスのリソースの包含をサポートしていない場合、400 Bad Request
で応答しなければならない。
注記: 例えば、関係パスは
comments.author
となる可能性があり、ここでcomments
はarticles
リソースオブジェクトの下にリストされている関係であり、author
はcomments
リソースオブジェクトの下にリストされている関係である。
例えば、記事と共にコメントを要求する場合
GET /articles/1?include=comments HTTP/1.1
Accept: application/vnd.api+json
他のリソースに関連するリソースを要求するには、各関係名に対してドット区切りのパスを指定できます。
GET /articles/1?include=comments.author HTTP/1.1
Accept: application/vnd.api+json
注記: 複合ドキュメントは完全なリンク付けを必要とするため(スパースフィールドセットによって関係リンク付けが除外される場合を除く)、複数部分パスの中間リソースは、リーフノードと共に返される必要がある。例えば、
comments.author
のリクエストに対するレスポンスには、comments
と、それらのcomments
のauthor
の両方が含まれる必要がある。
注記: サーバーは、
comments.author
などの深くネストされた関係を、commentAuthors
などの代替名を持つ直接的な関係として公開することを選択できる。これにより、クライアントは/articles/1?include=comments.author
の代わりに/articles/1?include=commentAuthors
を要求できる。ネストされた関係を代替名で公開することで、サーバーは潜在的に不要な中間リソースを含めることなく、複合ドキュメントで完全なリンク付けを提供できる。
複数の関連リソースをコンマ区切りのリストで要求できる。
GET /articles/1?include=comments.author,ratings HTTP/1.1
Accept: application/vnd.api+json
さらに、関連リソースは関係エンドポイントから要求できる。
GET /articles/1/relationships/comments?include=comments.author HTTP/1.1
Accept: application/vnd.api+json
この場合、主要データは記事のコメントへのリンクを表すリソース識別子オブジェクトのコレクションであり、完全なコメントとコメントの作者は含まれるデータとして返される。
注記: このセクションは、リクエストの種類に関係なく、主要データで応答するエンドポイントすべてに適用されます。例えば、サーバーは、リソースまたは関係を作成する
POST
リクエストと共に、関連リソースの包含をサポートできる。
スパースフィールドセット
クライアントは、fields[TYPE]
クエリパラメータを含めることで、エンドポイントがタイプごとにレスポンスで特定のフィールドのみを返すように要求できる。
任意のfields[TYPE]
パラメータの値は、返すフィールドの名前を参照するコンマ区切り(U+002C COMMA、「、」)のリストでなければならない。空の値は、フィールドを返さないことを示す。
クライアントが特定のリソースタイプに対して制限されたフィールドセットを要求した場合、エンドポイントは、そのタイプのレスポンスのリソースオブジェクトに追加のフィールドを含めてはならない。
クライアントが特定のリソースタイプのフィールドセットを指定しない場合、サーバーは、そのリソースタイプに対してすべてのフィールド、フィールドのサブセット、またはフィールドなしを送信できる。
GET /articles?include=author&fields[articles]=title,body&fields[people]=name HTTP/1.1
Accept: application/vnd.api+json
注記: 上記のURIの例では、可読性を高めるため、エンコードされていない
[
と]
文字を示しています。実際には、これらの文字はパーセントエンコードする必要があります。「パラメータ名の大括弧」を参照してください。
注記: このセクションは、リクエストの種類に関係なく、主要データまたは含まれるデータとしてリソースで応答するエンドポイントすべてに適用されます。例えば、サーバーは、リソースを作成する
POST
リクエストと共に、スパースフィールドセットをサポートできる。
並べ替え
サーバーは、1つ以上の基準(「ソートフィールド」)に従ってリソースコレクションをソートするリクエストをサポートすることを選択できる。
注記: 推奨されるものの、ソートフィールドは必ずしもリソース属性名や関係名に対応する必要はない。
注記: ドット区切り(U+002E FULL-STOP、「.」)のソートフィールドを使用して、関係属性に基づいてソートを要求することをお勧めします。例えば、
author.name
というソートフィールドを使用して、author
関係のname
属性に基づいて主要データをソートするように要求できます。
エンドポイントは、sort
クエリパラメータを使用して主要データをソートするリクエストをサポートできる。sort
の値は、ソートフィールドを表す必要がある。
GET /people?sort=age HTTP/1.1
Accept: application/vnd.api+json
エンドポイントは、コンマ区切り(U+002C COMMA、「、」)のソートフィールドを許可することで、複数のソートフィールドをサポートできる。ソートフィールドは、指定された順序で適用されるべきである。
GET /people?sort=age,name HTTP/1.1
Accept: application/vnd.api+json
各ソートフィールドのソート順序は、ハイフン(U+002D HYPHEN-MINUS、「-」)を前に付けない限り昇順でなければならない。ハイフンを前に付けた場合は降順でなければならない。
GET /articles?sort=-created,title HTTP/1.1
Accept: application/vnd.api+json
上記の例では、最新の投稿が最初に返されます。同じ日付に作成された投稿は、タイトルの昇順でソートされます。
サーバーがクエリパラメータsort
で指定されたようにソートをサポートしていない場合、400 Bad Request
を返さなければならない。
サーバーがソートをサポートしており、クエリパラメータsort
を介してクライアントによって要求された場合、サーバーは、指定された基準に従って順序付けられたレスポンスの最上位レベルのdata
配列の要素を返さなければならない。リクエストパラメータsort
が指定されていない場合、サーバーは最上位レベルのdata
にデフォルトのソートルールを適用できる。
注記: このセクションは、リクエストの種類に関係なく、リソースコレクションを主要データとして返すエンドポイントすべてに適用されます。
ページネーション
サーバーは、レスポンスで返されるリソースの数を、利用可能な全セットのサブセット(「ページ」)に制限することを選択できる。
サーバーは、ページネーションされたデータセットをトラバースするためのリンク(「ページネーションリンク」)を提供できる。
ページネーションリンクは、コレクションに対応するlinksオブジェクトに表示されなければならない。主要データをページネーションするには、最上位レベルのlinks
オブジェクトにページネーションリンクを指定する。 複合ドキュメントで返される含まれるコレクションをページネーションするには、対応するlinksオブジェクトにページネーションリンクを指定する。
次のキーは、ページネーションリンクに使用されなければならない。
first
: データの最初のページlast
: データの最後のページprev
: データの前のページnext
: データの次のページ
キーは、省略するか、特定のリンクが使用できないことを示すnull
値を持つ必要がある。
ページネーションリンクの命名で表される順序の概念は、JSON:APIのソートルールと一貫していなければならない。
page
クエリパラメータファミリは、ページネーションのために予約されている。サーバーとクライアントは、ページネーション操作にこれらのパラメータを使用するべきである。
注記: JSON APIは、サーバーで使用されるページネーション戦略についてアグノスティックであるが、
page
クエリパラメータファミリは、使用される戦略に関係なく使用できる。例えば、ページベースの戦略ではpage[number]
とpage[size]
などのクエリパラメータを使用できる一方、カーソルベースの戦略ではpage[cursor]
を使用できる。
注記: このセクションは、リクエストの種類に関係なく、リソースコレクションを主要データとして返すエンドポイントすべてに適用されます。
フィルタリング
filter
クエリパラメータファミリは、データのフィルタリングのために予約されている。サーバーとクライアントは、フィルタリング操作にこれらのパラメータを使用するべきである。
注記: JSON APIは、サーバーでサポートされる戦略についてアグノスティックです。
リソースの作成、更新、削除
サーバーは、特定のタイプの資源の作成を許可できる。また、既存のリソースの変更や削除も許可できる。
リクエストは、完全に成功するか、失敗する必要がある(単一の「トランザクション」で)。部分的な更新は許可されない。
注記:
type
メンバーは、JSON:APIのリクエストとレスポンス全体で、すべてのリソースオブジェクトで必須である。異種データを表現するエンドポイントにPOST
する場合など、type
をエンドポイントから推測できない場合がある。しかし、いつ必須でいつそうでないかを区別することは混乱を招く。いつ必須でいつそうでないかを覚えるのは難しいだろう。したがって、一貫性を向上させ、混乱を最小限に抑えるために、type
は常に必須である。
リソースの作成
リソースは、リソースのコレクションを表すURLにPOST
リクエストを送信することで作成できる。リクエストは、主要データとして単一のリソースオブジェクトを含んでいなければならない。リソースオブジェクトは、少なくともtype
メンバーを含んでいなければならない。
例えば、新しい写真は次のリクエストで作成できる。
POST /photos HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": {
"type": "photos",
"attributes": {
"title": "Ember Hamster",
"src": "http://example.com/images/productivity.png"
},
"relationships": {
"photographer": {
"data": { "type": "people", "id": "9" }
}
}
}
}
リソースオブジェクトのリソースオブジェクトのrelationships
メンバーにリレーションシップが指定されている場合、その値はdata
メンバーを持つリレーションシップオブジェクト**でなければなりません**。このキーの値は、新規リソースが持つリンクを表します。
クライアント生成ID
サーバは、リソース作成のリクエストとともにクライアント生成IDを**受け入れる場合があります**。IDはid
キーで指定する**必要**があり、その値はグローバルに一意な識別子**でなければなりません**。クライアントは、RFC 4122 [RFC4122]で説明されているように、適切に生成およびフォーマットされたUUIDを使用する**べきです**。
注記: 別のソースからのデータインポートなど、一部のユースケースでは、グローバルに一意であることが保証されているUUID以外のものを使用できる場合があります。使用している戦略が実際にグローバルに一意な識別子を生成することを100%確信していない限り、UUID以外のものを使用しないでください。
例:
POST /photos HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": {
"type": "photos",
"id": "550e8400-e29b-41d4-a716-446655440000",
"attributes": {
"title": "Ember Hamster",
"src": "http://example.com/images/productivity.png"
}
}
}
サーバは、クライアント生成IDを持つリソースを作成するサポートされていないリクエストに応答して、403 Forbidden
を**返さなければなりません**。
レスポンス
201 Created
要求されたリソースが正常に作成され、サーバが何らかの方法でリソースを変更した場合(例:id
の割り当て)、サーバは201 Created
レスポンスと、リソースを主要データとして含むドキュメントを**返さなければなりません**。
レスポンスには、RFC 7231に準拠するために、新しく作成されたリソースの場所を示すLocation
ヘッダーを含める**べきです**。
レスポンスによって返されたリソースオブジェクトが、そのlinks
メンバーにself
キーを含み、Location
ヘッダーが提供されている場合、self
メンバーの値はLocation
ヘッダーの値と**一致しなければなりません**。
HTTP/1.1 201 Created
Location: http://example.com/photos/550e8400-e29b-41d4-a716-446655440000
Content-Type: application/vnd.api+json
{
"data": {
"type": "photos",
"id": "550e8400-e29b-41d4-a716-446655440000",
"attributes": {
"title": "Ember Hamster",
"src": "http://example.com/images/productivity.png"
},
"links": {
"self": "http://example.com/photos/550e8400-e29b-41d4-a716-446655440000"
}
}
}
要求されたリソースが正常に作成され、サーバがリソースを何らかの方法で変更しない場合(例:id
またはcreatedAt
属性の割り当て)、サーバは主要データを含まないドキュメントで201 Created
レスポンスを**返す場合があります**。metaなどの他のトップレベルメンバーは、レスポンスドキュメントに含まれる可能性があります。
注記: クライアント生成IDを受け入れるサーバのみが、新規リソースへの
id
の割り当てを回避できます。
202 Accepted
リソース作成のリクエストが処理のために受け入れられたが、サーバが応答するまでに処理が完了していない場合、サーバは202 Accepted
ステータスコードを**返さなければなりません**。
204 No Content
要求されたリソースが正常に作成され、サーバがリソースを何らかの方法で変更しない場合(例:id
またはcreatedAt
属性の割り当て)、サーバは201 Created
ステータスコードとレスポンスドキュメント(上記で説明)または204 No Content
ステータスコードとレスポンスドキュメントなしを**返さなければなりません**。
403 Forbidden
サーバは、リソースの作成に関するサポートされていないリクエストに応答して403 Forbidden
を**返す場合があります**。
404 Not Found
関連するリソースが存在しないことを参照するリクエストを処理する場合、サーバは404 Not Found
を**返さなければなりません**。
409 Conflict
既に存在するクライアント生成IDを持つリソースを作成するためのPOST
リクエストを処理する場合、サーバは409 Conflict
を**返さなければなりません**。
リソースオブジェクトのtype
が、エンドポイントによって表されるコレクションを構成する型に含まれていないPOST
リクエストを処理する場合、サーバは409 Conflict
を**返さなければなりません**。
サーバは、エラーの詳細を含め、競合の原因を認識するのに十分な情報を提供する**べきです**。
その他のレスポンス
サーバーは、その他のHTTPステータスコードで応答できます。
サーバーは、エラーレスポンスにエラーの詳細を含めることができます。
サーバーはHTTPセマンティクス
に従ってレスポンスを準備する必要があり、クライアントはレスポンスを解釈する必要があります。
リソースの更新
リソースは、リソースを表すURLにPATCH
リクエストを送信することで更新できます。
リソースのURLは、リソースオブジェクトのself
リンクから取得できます。あるいは、GET
リクエストが主要データとして単一のリソースオブジェクトを返す場合、同じリクエストURLを更新に使用できます。
PATCH
リクエストには、主要データとして単一のリソースオブジェクトを含める**必要**があります。リソースオブジェクトには、type
とid
メンバーを含める**必要**があります。
例:
PATCH /articles/1 HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": {
"type": "articles",
"id": "1",
"attributes": {
"title": "To TDD or Not"
}
}
}
リソース属性の更新
PATCH
リクエストに含まれるリソースオブジェクトには、リソースの属性の一部またはすべてを含める**場合があります**。
リクエストにリソースの属性のすべてが含まれていない場合、サーバは、欠落している属性を、現在の値で含まれているものとして解釈する**必要**があります。サーバは、欠落している属性をnull
値として解釈する**べきではありません**。
たとえば、次のPATCH
リクエストは、記事のtitle
属性とtext
属性のみを更新するリクエストとして解釈されます。
PATCH /articles/1 HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": {
"type": "articles",
"id": "1",
"attributes": {
"title": "To TDD or Not",
"text": "TLDR; It's complicated... but check your test coverage regardless."
}
}
}
リソースリレーションシップの更新
PATCH
リクエストに含まれるリソースオブジェクトには、リソースのリレーションシップの一部またはすべてを含める**場合があります**。
リクエストにリソースのリレーションシップのすべてが含まれていない場合、サーバは、欠落しているリレーションシップを、現在の値で含まれているものとして解釈する**必要**があります。null
または空の値として解釈する**べきではありません**。
PATCH
リクエストのリソースオブジェクトのrelationships
メンバーにリレーションシップが指定されている場合、その値はdata
メンバーを持つリレーションシップオブジェクト**でなければなりません**。リレーションシップの値は、このメンバーで指定された値に置き換えられます。
たとえば、次のPATCH
リクエストは、記事のauthor
リレーションシップを更新します。
PATCH /articles/1 HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": {
"type": "articles",
"id": "1",
"relationships": {
"author": {
"data": { "type": "people", "id": "1" }
}
}
}
}
同様に、次のPATCH
リクエストは、記事のtags
の完全な置換を実行します。
PATCH /articles/1 HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": {
"type": "articles",
"id": "1",
"relationships": {
"tags": {
"data": [
{ "type": "tags", "id": "2" },
{ "type": "tags", "id": "3" }
]
}
}
}
}
サーバは、多対多リレーションシップの完全な置換を試行することを**拒否する場合があります**。その場合、サーバは更新全体を拒否し、403 Forbidden
レスポンスを**返さなければなりません**。
注記: 完全な置換は非常に危険な操作である可能性があるため、サーバはそれを許可しないことを選択する場合があります。たとえば、サーバは、クライアントに関連オブジェクトの完全なリストを提供しておらず、クライアントが見ていないレコードの削除を許可したくない場合、完全な置換を拒否する場合があります。
レスポンス
200 OK
サーバが更新を受け入れるが、リクエストで指定されたもの以外の方法で対象リソースを変更する場合(例:updatedAt
属性または計算されたsha
の更新)、200 OK
レスポンスと、更新されたリソースを主要データとして含むドキュメントを**返さなければなりません**。
更新が成功し、サーバがリクエストで指定されたもの以外の方法で対象リソースを変更しない場合、サーバは主要データを含まないドキュメントで200 OK
レスポンスを**返す場合があります**。metaなどの他のトップレベルメンバーは、レスポンスドキュメントに含まれる可能性があります。
202 Accepted
更新リクエストが処理のために受け入れられたが、サーバが応答するまでに処理が完了していない場合、サーバは202 Accepted
ステータスコードを**返さなければなりません**。
204 No Content
更新が成功し、サーバがリクエストで指定されたもの以外の方法で対象リソースを変更しない場合、サーバは200 OK
ステータスコードとレスポンスドキュメント(上記で説明)または204 No Content
ステータスコードとレスポンスドキュメントなしを**返さなければなりません**。
403 Forbidden
リソースまたはリレーションシップを更新するサポートされていないリクエストに応答して、サーバは403 Forbidden
を**返さなければなりません**。
404 Not Found
存在しないリソースに対する変更要求を処理する場合、サーバーは404 Not Found
を**返さなければならない**。
関連するリソースが存在しないことを参照するリクエストを処理する場合、サーバは404 Not Found
を**返さなければなりません**。
409 Conflict
リソースを更新するPATCH
リクエストを処理する際に、その更新がサーバーで強制される制約(id
以外のプロパティの一意性制約など)に違反する場合、サーバーは409 Conflict
を**返すことができる**。
リソースオブジェクトのtype
またはid
がサーバーのエンドポイントと一致しないPATCH
リクエストを処理する場合、サーバーは409 Conflict
を**返さなければならない**。
サーバは、エラーの詳細を含め、競合の原因を認識するのに十分な情報を提供する**べきです**。
その他のレスポンス
サーバーは、その他のHTTPステータスコードで応答できます。
サーバーは、エラーレスポンスにエラーの詳細を含めることができます。
サーバーはHTTPセマンティクス
に従ってレスポンスを準備する必要があり、クライアントはレスポンスを解釈する必要があります。
リレーションシップの更新
リレーションシップはリソースと共に変更できます(上記参照)が、JSON:APIはリレーションシップリンクからのURLでリレーションシップを独立して更新することもサポートしています。
注記:リレーションシップは、外部キーなどの基盤となるサーバーのセマンティクスを公開せずに更新されます。さらに、関連リソースに影響を与えることなくリレーションシップを更新できます。たとえば、記事に複数の著者がいる場合、その人のデータを削除せずに、記事から著者の1人を削除できます。同様に、記事に複数のタグがある場合、タグを追加または削除できます。サーバー側では、これらの例のうち最初のものは外部キーで実装される可能性があり、2番目のものは結合テーブルで実装される可能性がありますが、JSON:APIプロトコルはどちらの場合も同じです。
注記:サーバーは、(ガベージコレクション対策として)リレーションシップが削除された場合、基盤となるリソースを削除することを選択できます。
一対一リレーションシップの更新
一対一のリレーションシップは、一対一のリレーションシップリンクからのURLにPATCH
リクエストを送信することで更新できます。
PATCH
リクエストは、新しい関連リソースに対応する、以下のいずれかを含むdata
という名前の最上位メンバーを**含む必要がある**。
- a リソース識別子オブジェクト
null
(リレーションシップを削除する場合)。
たとえば、次のリクエストは記事の著者を更新します。
PATCH /articles/1/relationships/author HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": { "type": "people", "id": "12" }
}
そして、次のリクエストは同じ記事の著者をクリアします。
PATCH /articles/1/relationships/author HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": null
}
リレーションシップが正常に更新された場合、サーバーは**正常なレスポンスを返さなければならない**。
一対多リレーションシップの更新
一対多のリレーションシップは、一対多のリレーションシップリンクからのURLにPATCH
、POST
、またはDELETE
リクエストを送信することで更新できます。
すべてのリクエストタイプについて、本文はdata
メンバーを含んでいなければならず、その値は空の配列かリソース識別子オブジェクトの配列でなければなりません。
クライアントが、一対多のリレーションシップリンクからのURLにPATCH
リクエストを行う場合、サーバーはリレーションシップのすべてのメンバーを完全に置き換えるか、一部のリソースが見つからないかアクセスできない場合は適切なエラー応答を返すか、サーバーで完全な置換が許可されていない場合は403 Forbidden
応答を**返さなければならない**。
たとえば、次のリクエストは記事のすべてのタグを置き換えます。
PATCH /articles/1/relationships/tags HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": [
{ "type": "tags", "id": "2" },
{ "type": "tags", "id": "3" }
]
}
そして、次のリクエストは記事のすべてのタグをクリアします。
PATCH /articles/1/relationships/tags HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": []
}
クライアントがリレーションシップリンクからのURLにPOST
リクエストを行う場合、サーバーは指定されたメンバーが既に存在しない限り、リレーションシップに指定されたメンバーを追加**しなければならない**。指定されたtype
とid
が既にリレーションシップに存在する場合は、サーバーは再度追加**してはならない**。
注記:これは、多対多リレーションシップに外部キーを使用するデータベースのセマンティクスと一致します。ドキュメントベースのストレージは、重複を避けるために、追加する前に多対多リレーションシップを確認する必要があります。
指定されたすべてのリソースがリレーションシップに追加できるか、既にリレーションシップに存在する場合は、サーバーは**正常なレスポンスを返さなければならない**。
注記:このアプローチにより、サーバーの状態が要求された状態と一致する場合にリクエストが成功し、複数のクライアントがリレーションシップに同じ変更を加えることによって発生する無意味な競合状態を回避するのに役立ちます。
次の例では、ID 123
のコメントが、ID 1
の記事のコメントリストに追加されます。
POST /articles/1/relationships/comments HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": [
{ "type": "comments", "id": "123" }
]
}
クライアントがリレーションシップリンクからのURLにDELETE
リクエストを行う場合、サーバーはリレーションシップから指定されたメンバーを削除するか、403 Forbidden
応答を**返さなければならない**。指定されたすべてのリソースがリレーションシップから削除できるか、既にリレーションシップに存在しない場合は、サーバーは**正常なレスポンスを返さなければならない**。
注記:上記
POST
リクエストについて説明したように、このアプローチは、複数のクライアントが同じ変更を行うことによる無意味な競合状態を回避するのに役立ちます。
リレーションシップメンバーは、POST
リクエストの場合と同じ方法で指定されます。
次の例では、ID 12
と13
のコメントが、ID 1
の記事のコメントリストから削除されます。
DELETE /articles/1/relationships/comments HTTP/1.1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
"data": [
{ "type": "comments", "id": "12" },
{ "type": "comments", "id": "13" }
]
}
注記:RFC 7231では、DELETEリクエストに本文を含めることができるが、サーバーがリクエストを拒否できることが指定されています。この仕様ではサーバーのセマンティクスを定義しており、JSON:APIのセマンティクスを定義しています。
レスポンス
200 OK
サーバーが更新を受け入れるが、リクエストで指定されたもの以外の方法で対象のリレーションシップを変更する場合、200 OK
レスポンスと、更新されたリレーションシップデータを主データとして含むドキュメントを**返さなければならない**。
更新が成功し、サーバーがリクエストで指定されたもの以外の方法で対象のリレーションシップを変更しない場合、サーバーは主データを含まない200 OK
レスポンスを**返すことができる**。 metaなどの他の最上位メンバーをレスポンスドキュメントに含めることができます。
202 Accepted
リレーションシップ更新リクエストが処理のために受け入れられたが、サーバーが応答するまでに処理が完了していない場合、サーバーは202 Accepted
ステータスコードを**返さなければならない**。
204 No Content
更新が成功し、サーバーがリクエストで指定されたもの以外の方法で対象のリレーションシップを変更しない場合、サーバーは200 OK
ステータスコードとレスポンスドキュメント(上記参照)またはレスポンスドキュメントを含まない204 No Content
ステータスコードのいずれかを**返さなければならない**。
注記:これは、一対多のリレーションシップリンクからのURLに送信された
POST
リクエストで、そのリレーションシップが既に存在する場合の適切なレスポンスです。また、一対多のリレーションシップリンクからのURLに送信されたDELETE
リクエストで、そのリレーションシップが存在しない場合の適切なレスポンスでもあります。
403 Forbidden
サーバーは、リレーションシップを更新するサポートされていないリクエストに応答して403 Forbidden
を**返さなければならない**。
その他のレスポンス
サーバーは、その他のHTTPステータスコードで応答できます。
サーバーは、エラーレスポンスにエラーの詳細を含めることができます。
サーバーはHTTPセマンティクス
に従ってレスポンスを準備する必要があり、クライアントはレスポンスを解釈する必要があります。
リソースの削除
リソースは、リソースを表すURLにDELETE
リクエストを送信することで削除できます。
DELETE /photos/1 HTTP/1.1
Accept: application/vnd.api+json
レスポンス
200 OK
削除リクエストが成功した場合、サーバーは主データを含まない200 OK
レスポンスを**返すことができる**。 metaなどの他の最上位メンバーをレスポンスドキュメントに含めることができます。
202 Accepted
削除リクエストが処理のために受け入れられたが、サーバーが応答するまでに処理が完了していない場合、サーバーは202 Accepted
ステータスコードを**返さなければならない**。
204 No Content
削除リクエストが成功した場合、サーバーは200 OK
ステータスコードとレスポンスドキュメント(上記参照)またはレスポンスドキュメントを含まない204 No Content
ステータスコードのいずれかを**返さなければならない**。
404 NOT FOUND
リソースが存在しないために削除リクエストが失敗した場合、サーバーは404 Not Found
ステータスコードを**返すのが望ましい**。
その他のレスポンス
サーバーは、その他のHTTPステータスコードで応答できます。
サーバーは、エラーレスポンスにエラーの詳細を含めることができます。
サーバーはHTTPセマンティクス
に従ってレスポンスを準備する必要があり、クライアントはレスポンスを解釈する必要があります。
クエリパラメータ
クエリパラメータファミリ
「クエリパラメータ」は日常的なWeb開発では一般的な用語ですが、標準化された概念ではありません。そのため、JSON:APIは独自のクエリパラメータの定義を提供します。
ほとんどの場合、JSON:APIの定義は口語的な用法と一致しており、その詳細は無視しても問題ありません。ただし、この定義の重要な結果の1つは、次のURLのようなものが2つの異なるクエリパラメータを持つと見なされることです。
/?page[offset]=0&page[limit]=10
2つのパラメータの名前はpage[offset]
とpage[limit]
です。page
という単一のパラメータはありません。
しかし実際には、page[offset]
やpage[limit]
のようなパラメータは通常一緒に定義および処理され、それらをまとめて参照することが便利です。そのため、JSON:APIはクエリパラメータファミリーという概念を導入します。
「クエリパラメータファミリー」とは、名前が「基本名」で始まり、それに0個以上の空の角括弧(つまり[]
)、角括弧で囲まれた有効なメンバー名、または角括弧で囲まれたドットで区切られた有効なメンバー名のリストが続く、すべてのクエリパラメータの集合です。ファミリーは基本名で参照されます。
たとえば、filter
クエリパラメータファミリーには、filter
、filter[x]
、filter[]
、filter[x][]
、filter[][]
、filter[x][y]
、filter[x.y]
などが含まれます。ただし、_
は有効なメンバー名ではないため、filter[_]
はファミリー内の有効なパラメータ名ではありません。
注:ドットで区切られた有効なメンバー名のリストは、リレーションシップパスのために使用することを目的としています。たとえば、これにより、
GET /posts?sort=author.name&filter[author.status]=active
などのクエリパラメータでソート/取得のための定義に従って、リレーションシップパスを使用したフィルタリング戦略が可能になります。[ソート][取得時のソート]
拡張機能固有のクエリパラメータ
拡張機能によって導入されたすべてのクエリパラメータの基本名は、拡張機能の名前空間をコロン(:
)で接頭辞として付ける**必要があります**。基本名の残りの部分は、[a-z](U+0061~U+007A、「a-z」)の文字のみを含める**必要があります**。
実装固有のクエリパラメータ
実装では、カスタムクエリパラメータをサポートしても**かまいません**。ただし、これらのクエリパラメータの名前は、基本名が有効なメンバー名であり、かつ少なくとも1つのa-z以外の文字(つまり、U+0061~U+007A以外)を含むファミリーに由来する**必要があります**。
上記の要件を満たすために、大文字(例:キャメルケース)を使用することを**推奨**します。
サーバーが上記の命名規則に従っていないクエリパラメータを検出した場合、またはサーバーがこの仕様からのクエリパラメータとして処理する方法がわからない場合、400 Bad Request
を返す**必要があります**。
注:[a-z]の文字のみを含むクエリパラメータの使用を禁止することにより、JSON:APIは、既存の実装と競合することなく、後で追加のクエリパラメータを標準化する能力を確保しています。
エラー
エラー処理
サーバーは、問題が発生した時点で処理を停止するか、処理を続行して複数の問題が発生するよう選択しても**かまいません**。たとえば、サーバーは複数の属性を処理してから、単一のレスポンスで複数の検証問題を返す場合があります。
サーバーが単一の要求に対して複数の問題を検出した場合、最も一般的に適用できるHTTPエラーコードをレスポンスで使用**する必要があります**。たとえば、複数の4xxエラーには400 Bad Request
が、複数の5xxエラーには500 Internal Server Error
が適切な場合があります。
エラーオブジェクト
エラーオブジェクトは、操作の実行中に発生した問題に関する追加情報を提供します。エラーオブジェクトは、JSON:APIドキュメントの最上位レベルでerrors
というキーを持つ配列として返す**必要があります**。
エラーオブジェクトは次のメンバーを持つことができ、少なくとも1つを含める**必要があります**。
id
:この特定の問題の発生に関する一意の識別子。links
:次のメンバーを含むことができるリンクオブジェクト。status
:この問題に適用できるHTTPステータスコードを文字列値で表したもの。これは提供**する必要があります**。code
:アプリケーション固有のエラーコードを文字列値で表したもの。title
:問題の簡潔で人間が読める要約。ローカライズ目的を除き、問題の発生ごとに変更されるべきではありません。detail
:この問題の発生に関する人間が読める説明。title
と同様に、このフィールドの値はローカライズできます。source
:エラーの主要なソースへの参照を含むオブジェクト。次のメンバーのいずれかを含めるか、省略する**必要があります**。pointer
:要求ドキュメント内でエラーの原因となった値へのJSON Pointer [RFC6901](例:主データオブジェクトの場合は"/data"
、特定の属性の場合は"/data/attributes/title"
)。これは、存在する要求ドキュメント内の値を指す**必要があります**。そうでない場合、クライアントはポインタを無視する**必要があります**。parameter
:エラーの原因となったURIクエリパラメータを示す文字列。header
:エラーの原因となった単一の要求ヘッダーの名前を示す文字列。
meta
:エラーに関する標準外のメタ情報を含むメタオブジェクト。
付録
クエリパラメータの詳細
パース/シリアライズ
クエリパラメータは、URIのクエリ文字列から抽出されるか、URIのクエリ文字列にシリアライズされる名前と値のペアです。
URIからクエリパラメータを抽出するために、実装は先頭の疑問符を除いたURIのクエリ文字列をapplication/x-www-form-urlencoded
パースアルゴリズムに通す**必要があります**。ただし、例外として、JSON:APIでは、クエリパラメータの使用を定義する仕様が、application/x-www-form-urlencoded
パースアルゴリズムのステップ3.2と3.3で識別されたvalue
バイトからパラメータの値をパースするための独自のルールを提供することを許可しています。結果の値は文字列ではない可能性があります。
注:一般的に、サーバーやブラウザに組み込まれているクエリ文字列のパースは上記で指定されたプロセスと一致するため、ほとんどの実装ではこれについて心配する必要はありません。
application/x-www-form-urlencoded
形式は、今日のほとんどすべてのクエリ文字列が使用するa=b&c=d
スタイルの基礎であるため参照されています。ただし、
application/x-www-form-urlencoded
のパースには、+
文字をスペースとして扱うという奇妙な歴史的遺物があり、すべての値をパース中にパーセントデコードする必要があるため、RFC 3986区切り文字を区切り文字として使用することができません。これらの問題は、JSON:APIが上記で定義する例外の動機となっています。
同様に、クエリパラメータをURIにシリアライズするには、実装はapplication/x-www-form-urlencoded
シリアライザを使用する**必要があります**。対応する例外として、パラメータの値(ただし、名前ではない)は、シリアライズが結果のURIをパースする能力を妨げない限り、アルゴリズムが要求するとは異なる方法でシリアライズできます。
パラメータ名における角括弧
クエリパラメータファミリーを使用すると、JSON:APIでは、名前が角括弧(つまり、U+005B「[」とU+005D「]」)を含むクエリパラメータを使用できます。
上記のクエリパラメータシリアライズルールに従って、準拠した実装ではこれらの角括弧をパーセントエンコードします。ただし、一部のURIプロデューサ(つまりブラウザ)は、常にそれらをエンコードするとは限りません。サーバーは、これらの角括弧がクエリパラメータの名前にエンコードされていない状態で受け入れた要求を受け入れる**必要があります**。サーバーがこれらの要求を受け入れる場合、角括弧がパーセントエンコードされたものと等価な要求として処理する**必要があります**。