RESTful APIでページネーションをサポートしたい。
APIメソッドは、/products/index
を介して製品のJSONリストを返す必要があります。ただし、潜在的に何千もの製品があり、それらをページングしたいので、私のリクエストは次のようになります。
/products/index?page_number=5&page_size=20
しかし、JSON応答はどのように見える必要がありますか? APIコンシューマーは通常、応答でページネーションメタデータを期待しますか?または、製品の配列だけが必要ですか?どうして?
TwitterのAPIにはメタデータが含まれているようです: https://dev.Twitter.com/docs/api/1/get/lists/members (リクエストの例を参照)。
メタデータの場合:
{
"page_number": 5,
"page_size": 20,
"total_record_count": 521,
"records": [
{
"id": 1,
"name": "Widget #1"
},
{
"id": 2,
"name": "Widget #2"
},
{
"id": 3,
"name": "Widget #3"
}
]
}
製品の配列(メタデータなし):
[
{
"id": 1,
"name": "Widget #1"
},
{
"id": 2,
"name": "Widget #2"
},
{
"id": 3,
"name": "Widget #3"
}
]
ReSTful APIは主に他のシステムによって消費されるため、応答ヘッダーにページングデータを入れています。ただし、一部のAPIコンシューマーは、応答ヘッダーに直接アクセスできない場合や、APIを介してUXを構築する場合があるため、JSON応答のメタデータを(オンデマンドで)取得する方法を提供することはプラスです。
実装には、デフォルトで機械可読メタデータを含め、要求された場合は人間可読メタデータを含める必要があると思います。人間が読めるメタデータは、必要に応じてすべてのリクエストで返されるか、include=metadata
やinclude_metadata=true
などのクエリパラメータを介してオンデマンドで返されることができます。
特定のシナリオでは、各製品のURIをレコードに含めます。これにより、APIコンシューマーは個々の製品へのリンクを簡単に作成できます。また、ページング要求の制限に従って、合理的な期待値を設定します。ページサイズのデフォルト設定を実装して文書化することは、受け入れられるプラクティスです。たとえば、 GitHubのAPI は、デフォルトのページサイズを最大100の30レコードに設定し、さらにAPIをクエリできる回数のレート制限を設定します。 APIにデフォルトのページサイズがある場合、クエリ文字列はページインデックスを指定するだけです。
人間が読めるシナリオでは、/products?page=5&per_page=20&include=metadata
に移動すると、応答は次のようになります。
{
"_metadata":
{
"page": 5,
"per_page": 20,
"page_count": 20,
"total_count": 521,
"Links": [
{"self": "/products?page=5&per_page=20"},
{"first": "/products?page=0&per_page=20"},
{"previous": "/products?page=4&per_page=20"},
{"next": "/products?page=6&per_page=20"},
{"last": "/products?page=26&per_page=20"},
]
},
"records": [
{
"id": 1,
"name": "Widget #1",
"uri": "/products/1"
},
{
"id": 2,
"name": "Widget #2",
"uri": "/products/2"
},
{
"id": 3,
"name": "Widget #3",
"uri": "/products/3"
}
]
}
機械可読なメタデータの場合、応答に Link headers を追加します。
Link: </products?page=5&perPage=20>;rel=self,</products?page=0&perPage=20>;rel=first,</products?page=4&perPage=20>;rel=previous,</products?page=6&perPage=20>;rel=next,</products?page=26&perPage=20>;rel=last
(Linkヘッダー値はurlencodedである必要があります)
...そして場合によってはカスタムtotal-count
応答ヘッダーも選択します:
total-count: 521
人間中心のメタデータで明らかになった他のページングデータは、マシン中心のメタデータには不要な場合があります。これは、リンクヘッダーにより、現在のページとページごとの数が通知され、配列内のレコード数をすばやく取得できるためです。したがって、おそらく合計カウントのヘッダーのみを作成します。後からいつでも気を変えて、メタデータを追加できます。
余談ですが、/index
をURIから削除したことに気付くかもしれません。一般的に受け入れられている規則は、ReSTエンドポイントにコレクションを公開することです。末尾に/index
を付けると、それが少し増えます
これらは、APIを使用/作成するときに必要なもののほんの一部です。お役に立てば幸いです!
RESTサービスを利用するためにいくつかのライブラリを書いた人として、メタデータで結果をラッピングすることがどうすればよいのかについてクライアントの視点から説明させてください。
提案: Twitter API と同様に、page_numberをストレートインデックス/カーソルに置き換える必要があります。その理由は、APIにより、クライアントがリクエストごとにページサイズを設定できるからです。返されたpage_numberは、クライアントがこれまでに要求したページ数、または最後に使用されたpage_sizeが与えられたページの数ですか(ほぼ間違いなく、しかし、このようなあいまいさを完全に回避しないのはなぜですか)?
同じためにヘッダーを追加することをお勧めします。メタデータをヘッダーに移動すると、result
、data
、またはrecords
などのエンベロープを削除するのに役立ち、応答本文には必要なデータのみが含まれます。ページネーションリンクも生成する場合は、 Link headerを使用できます。
HTTP/1.1 200
Pagination-Count: 100
Pagination-Page: 5
Pagination-Limit: 20
Content-Type: application/json
[
{
"id": 10,
"name": "shirt",
"color": "red",
"price": "$23"
},
{
"id": 11,
"name": "shirt",
"color": "blue",
"price": "$25"
}
]
詳細については、以下を参照してください。
https://github.com/adnan-kamili/rest-api-response-format
Swaggerファイルの場合: