推奨事項

このセクションでは、JSON:API実装に関する推奨事項を記載しています。これらの推奨事項は、基本的なJSON:API仕様の範囲を超えた領域における一貫性のレベルを確立することを目的としています。

ネーミング

仕様では、JSON:APIドキュメントのメンバ(つまり、キー)の命名方法に特定の厳格な制限を設けています。特に、異なる関係者によって作成されたプロファイルが混在する場合にメンバ名をさらに標準化するために、次のルールも推奨されます。

  • メンバ名は、**キャメルケース**にすることを**推奨**します(例:wordWordWord)。
  • メンバ名は、「a-z」(U+0061~U+007A)の文字で始めることと終わることを**推奨**します。
  • メンバ名は、ASCII英数字(つまり、「a-z」、「A-Z」、「0-9」)のみを含むことを**推奨**します。

URL設計

参照ドキュメント

APIのURL構造を決定する際には、そのすべてのリソースが単一の「参照ドキュメント」に存在し、各リソースが一意のパスでアクセス可能であることを考慮することが役立ちます。リソースは、このドキュメントの最上位レベルでタイプ別にグループ化されます。個々のリソースは、これらのタイプ分けされたコレクション内でIDによってキー付けされます。個々のリソース内の属性とリンクは、上記で説明されているリソースオブジェクト構造に従って一意にアクセス可能です。

この参照ドキュメントの概念は、リソースとその関係の適切なURLを決定するために使用されます。この参照ドキュメントは、異なる目標と制約のために、リソースの転送に使用されるドキュメントとは構造がわずかに異なることを理解することが重要です。たとえば、参照ドキュメントのコレクションは、メンバがIDでアクセス可能である必要があるため集合として表現されますが、転送ドキュメントのコレクションは、順序が重要であるため配列として表現されます。

リソースコレクションのURL

リソースのコレクションのURLは、リソースタイプから形成することをお勧めします。

たとえば、タイプphotosのリソースのコレクションのURLは次のようになります。

/photos

個々のリソースのURL

リソースのコレクションを、リソースIDによってキー付けされた集合として扱います。個々のリソースのURLは、コレクションのURLにリソースのIDを追加することで形成できます。

たとえば、IDが"1"の写真のURLは次のようになります。

/photos/1

基本仕様で説明されているように、各リレーションシップに対して公開できるURLは2つあります。

  • 「リレーションシップURL」 - リレーションシップ自体のURL。これは、リレーションシップのlinksオブジェクト内のselfキーで識別されます。このURLにより、クライアントはリレーションシップを直接操作できます。たとえば、peopleリソース自体を削除せずに、postからauthorを削除できます。

  • 「関連リソースURL」 - 関連リソースのURL。これは、リレーションシップのlinksオブジェクト内のrelatedキーで識別されます。フェッチされると、関連リソースオブジェクトがレスポンスの主要なデータとして返されます。

リレーションシップURLは、リソースのURLに/relationships/とリレーションシップの名前を追加して形成することをお勧めします。

たとえば、写真のcommentsリレーションシップのURLは次のようになります。

/photos/1/relationships/comments

そして、写真のphotographerリレーションシップのURLは次のようになります。

/photos/1/relationships/photographer

関連リソースURLは、リソースのURLにリレーションシップの名前を追加して形成することをお勧めします。

たとえば、写真のcommentsのURLは次のようになります。

/photos/1/comments

そして、写真のphotographerのURLは次のようになります。

/photos/1/photographer

これらのURLはリレーションシップのリソースを表しているため、リソース自体のselfリンクとして使用しないでください。selfリンクを形成する際には、個々のリソースURLの推奨事項を適用する必要があります。

フィルタリング

基本仕様では、サーバでサポートされるフィルタリング戦略については触れていません。filterクエリパラメータファミリは、フィルタリング戦略の基礎として使用するために予約されています。

関連付けに基づいてリソースコレクションのフィルタリングをサポートするサーバは、filterと関連付けの名前を組み合わせたクエリパラメータを許可することでフィルタリングを行うことをお勧めします。

たとえば、特定の投稿に関連付けられたすべてのコメントを要求する例を以下に示します。

GET /comments?filter[post]=1 HTTP/1.1

複数のフィルタ値をコンマ区切りのリストで組み合わせることができます。例:

GET /comments?filter[post]=1,2 HTTP/1.1

さらに、複数のフィルタを単一の要求に適用できます。

GET /comments?filter[post]=1,2&filter[author]=12 HTTP/1.1

基本仕様では、リソースレスポンスにリンクを含めることについては触れていません。ただし、レスポンスドキュメントには次のリンクを含めることをお勧めします。

  • **トップレベルリンク**(レスポンス全体に対するセルフリンクなど)と、相対的なページネーションリンク(該当する場合)。
  • **リソースレベルリンク**(リソースがコレクションの一部である場合、トップレベルとは異なる各リソースのセルフリンクなど)。
  • **リレーションシップリンク**(リソースで使用可能なすべてのリレーションシップ)。

たとえば、コメントのコレクションを要求すると、次のレスポンスが返される可能性があります。

GET /comments HTTP/1.1

{
  "data": [{
      "type": "comments",
      "id": "1",
      "attributes": {
          "text": "HATEOS are the thing!"
      },
      "links": {
          "self": "/comments/1"
      },
      "relationships": {
        "author": {
          "links": {
            "self": "/comments/1/relationships/author",
            "related": "/comments/1/author"
          }
        },
        "articles": {
          "links": {
            "self": "/comments/1/relationships/articles",
            "related": "/comments/1/articles"
          }
        }
      }
  }],
  "links": {
      "self": "/comments"
  }
}

PATCHがないクライアントのサポート

IE8などの一部のクライアントは、HTTPのPATCHメソッドをサポートしていません。これらのクライアントをサポートするAPIサーバは、クライアントがX-HTTP-Method-Override: PATCHヘッダーを含んでいる場合、POST要求をPATCH要求として扱うことをお勧めします。これにより、PATCHをサポートしていないクライアントでも、ヘッダーを追加するだけで更新要求が処理されます。

日付と時刻のフィールドのフォーマット

JSON:APIは日付と時刻のフィールドの形式を指定しませんが、サーバがISO 8601に準拠することをお勧めします。このW3C NOTEでは、推奨される形式の概要を示しています。

非同期処理

リソースの作成が必要で、操作の完了に時間がかかる状況を考えてみましょう。

POST /photos HTTP/1.1

要求は、Content-Locationヘッダーにリンクを付けて202 Acceptedステータスを返す**べき**です。

HTTP/1.1 202 Accepted
Content-Type: application/vnd.api+json
Content-Location: https://example.com/photos/jobs/5234

{
  "data": {
    "type": "jobs",
    "id": "5234",
    "attributes": {
      "status": "Pending request, waiting other process"
    },
    "links": {
      "self": "/photos/jobs/5234"
    }
  }
}

ジョブプロセスのステータスを確認するために、クライアントは前に指定された場所に要求を送信できます。

GET /photos/jobs/5234 HTTP/1.1
Accept: application/vnd.api+json

保留中のジョブに対する要求は、サーバがステータスを正常に報告しているため、200 OKステータスを返す**べき**です。オプションとして、サーバはRetry-Afterヘッダーを返し、クライアントが再度確認するまでの待機時間をクライアントに指示することができます。Retry-After: 0を使用すると、1秒未満の再試行を推奨できます。

HTTP/1.1 200 OK
Content-Type: application/vnd.api+json
Retry-After: 10

{
  "data": {
    "type": "jobs",
    "id": "5234",
    "attributes": {
      "status": "Pending request, waiting other process"
    },
    "links": {
      "self": "/photos/jobs/5234"
    }
  }
}

ジョブプロセスが完了したら、要求はLocationヘッダーにリンクを付けて303 See otherステータスを返す**べき**です。

HTTP/1.1 303 See other
Content-Type: application/vnd.api+json
Location: https://example.com/photos/4577

プロファイルの作成

プロファイルは、ドキュメントの送信者がそのコンテンツに関する約束をするためのメカニズムであり、JSON:API仕様の基本的なセマンティクスを追加したり変更したりしません。たとえば、プロファイルでは、すべてのリソースオブジェクトにtimestamps属性フィールドがあり、timestampsオブジェクトのメンバはISO 8601日付時刻形式でフォーマットされることを示すことができます。

プロファイルは、これらの約束を独立して指定するものです。次の例は、上記のプロフィールの作成方法を示しています。

# Timestamps profile

## Introduction

This page specifies a profile for the `application/vnd.api+json` media type,
as described in the [JSON:API specification](https://jsonapi.dokyumento.jp/format/).

This profile allows every resource in a JSON:API document to represent
significant timestamps in a consistent way.

## Document Structure

Every resource object **MUST** include a `timestamps` member in its associated
`attributes` object. If this member is present, its value **MUST** be an object that
**MAY** contain at least one of the following members:

* `created`
* `updated`

The value of each member **MUST** comply with the variant of ISO 8601 used by
JavaScript's `JSON.stringify` method to format Javascript `Date` objects.