1. ホーム
  2. rest

[解決済み] RESTful API からのパジネーションレスポンスペイロード

2023-03-06 02:53:22

質問

RESTful APIでページネーションをサポートしたいのですが、どうすればよいですか?

私のAPIメソッドは、製品のJSONリストを /products/index . しかし、潜在的には何千もの製品があり、私はそれらをページングしたいので、私のリクエストは次のようになるはずです。

/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 は、デフォルトのページサイズを 30 レコード、最大 100 に設定し、さらに 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: </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ヘッダーの値はurlencodeされている必要があります)

...そして、おそらくカスタム total-count レスポンスヘッダもあります。

total-count: 521

人間中心のメタデータで明らかになった他のページングデータは、機械中心のメタデータには余計かもしれません。リンクヘッダによって、今いるページとページごとの数がわかり、配列内のレコード数をすぐに取得することができるからです。したがって、私はおそらく総数のヘッダのみを作成することになるでしょう。後で気が変わって、もっとメタデータを追加することはいつでも可能です。

余談ですが、私が /index を削除したことにお気づきでしょうか。一般的に受け入れられている慣習として、ReSTエンドポイントではコレクションを公開することになっています。そのためには /index をつけると、少し混乱します。

これらは、私がAPIを消費/作成するときに持っていたいいくつかの事柄です。お役に立てれば幸いです。