web-dev-qa-db-ja.com

RESTful APIからのページネーション応答ペイロード

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"
  }
]
69
Chad Johnson

ReSTful APIは主に他のシステムによって消費されるため、応答ヘッダーにページングデータを入れています。ただし、一部のAPIコンシューマーは、応答ヘッダーに直接アクセスできない場合や、APIを介してUXを構築する場合があるため、JSON応答のメタデータを(オンデマンドで)取得する方法を提供することはプラスです。

実装には、デフォルトで機械可読メタデータを含め、要求された場合は人間可読メタデータを含める必要があると思います。人間が読めるメタデータは、必要に応じてすべてのリクエストで返されるか、include=metadatainclude_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を使用/作成するときに必要なもののほんの一部です。お役に立てば幸いです!

88
codeprogression

RESTサービスを利用するためにいくつかのライブラリを書いた人として、メタデータで結果をラッピングすることがどうすればよいのかについてクライアントの視点から説明させてください。

  • 合計数がなければ、クライアントは、存在するすべてをまだ受信していないこと、および結果セットのページングを継続する必要があることをどのように知ることができますか?次のページの先読みを実行しなかったUIでは、最悪の場合、これは実際にはこれ以上データをフェッチしなかった[次へ]リンクとして表される場合があります。
  • 応答にメタデータを含めると、クライアントが追跡する状態が少なくなります。応答には要求の状態(この場合はデータセットへのカーソル)を再構築するために必要なメタデータが含まれているため、REST要求を応答と一致させる必要はありません。
  • 状態が応答の一部である場合、複数の要求を同じデータセットに同時に実行できます。また、要求が発生した順序で要求を処理できますが、要求を行った順序とは限りません。

提案: Twitter API と同様に、page_numberをストレートインデックス/カーソルに置き換える必要があります。その理由は、APIにより、クライアントがリクエストごとにページサイズを設定できるからです。返されたpage_numberは、クライアントがこれまでに要求したページ数、または最後に使用されたpage_sizeが与えられたページの数ですか(ほぼ間違いなく、しかし、このようなあいまいさを完全に回避しないのはなぜですか)?

27
Majix

同じためにヘッダーを追加することをお勧めします。メタデータをヘッダーに移動すると、resultdata、または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ファイルの場合:

https://github.com/adnan-kamili/swagger-response-template

12
adnan kamili