2012-08-28 19 views
54

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(Example Requestを参照)が含まれているようです。メタデータ付き

:製品の

{ 
    "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" 
    } 
    ] 
} 

ちょうど配列(なしメタデータ):RESTサービスを消費するためのいくつかのライブラリを書いた人として

[ 
    { 
    "id": 1, 
    "name": "Widget #1" 
    }, 
    { 
    "id": 2, 
    "name": "Widget #2" 
    }, 
    { 
    "id": 3, 
    "name": "Widget #3" 
    } 
] 

答えて

70

ReSTful APIは主に他のシステムで消費されるため、私はページングデータをレスポンスヘッダーに入れています。ただし、一部のAPIコンシューマーはレスポンスヘッダーに直接アクセスできない場合があります。また、APIを使用してUXを構築している場合もあります。そのため、JSONレスポンスのメタデータを(必要に応じて)取得する手段を提供することはプラスです。

私は、あなたの実装には、要求時に、機械で読めるメタデータをデフォルトで、人が読めるメタデータとして含めるべきだと思います。人間が読めるメタデータは、好きな場合にはすべてのリクエストと共に返され、好ましくはinclude=metadatainclude_metadata=trueなどのクエリパラメータを使用してオンデマンドで返されます。

特定のシナリオでは、各製品のURIをレコードに含めます。これにより、APIコンシューマは個々の製品へのリンクを簡単に作成できます。また、私のページング要求の制限に従っていくつかの合理的な期待を設定します。ページサイズのデフォルト設定を実装し文書化することは、許容される方法です。たとえば、GitHub's 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 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 

(リンクヘッダー値はURLエンコードされるべきです)

...おそらくカスタムtotal-countレスポンスヘッダ、あなたがそう選択した場合:

total-count: 521 

リンクヘッダは私が私が午前どのページ知っているとされるヒト中心のメタデータで明らかに他のページングデータは、マシン中心のメタデータのための余分かもしれません1ページあたりの数で、配列のレコード数をすばやく取得できます。したがって、私はおそらく総カウントのヘッダーを作成するだけです。後で心を変えて、メタデータを追加することができます。

脇に、あなたのURIから/indexを削除したことがあります。一般に受け入れられているコンベンションでは、ReSTエンドポイントにコレクションを公開させることです。末尾に/indexがあると、やや上向きです。

これらは、私がAPIを消費/作成するときに欲しいものです。希望が助けてくれる!

+0

per_pageは、page_size –

+1

'' page_count ":20'と' {"last": "/ products?page = 26&per_page = 20"} 'の規約に従っていませんか? –

+0

ページ1からページxまでのすべてのレコードを取得中に突然製品の数が増えるとどうなりますか? – MeV

23

、私はあなたに与えてみましょうなぜ結果をメタデータにラップすると思うのかについてのクライアントの視点があります。

  • どのようにしてクライアントがそれをすべて受け取っておらず、結果セットをページングし続けるべきかをクライアントがどのように知ることができますか?次のページを先読みしなかったUIでは、最悪の場合、これは実際にはそれ以上のデータをフェッチしなかったNext/Moreリンクとして表現される可能性があります。
  • メタデータをレスポンスに含めることで、クライアントはより少ない状態を追跡できます。リクエストの状態(この場合はデータセットへのカーソル)を再構築するために必要なメタデータがレスポンスに含まれているため、RESTリクエストとレスポンスを一致させる必要はありません。
  • 状態が応答の一部である場合、私は同じデータセットに複数の要求を同時に実行できます。到着した順番に要求を処理できますが、必ずしも要求を行った順序ではありません。

また、Twitter APIと同様に、page_numberをまっすぐなインデックス/カーソルに置き換える必要があります。理由は、APIがクライアントに要求ごとのページサイズを設定させるためです。返されたpage_numberは、クライアントがこれまでに要求したページ数、または最後に使用されたpage_sizeを与えられたページの数です(ほとんど間違いなく、あいまいさを避けてください)。

+5

:闊歩ファイルについて

https://github.com/adnan-kamili/rest-api-response-format

次のページがない場合はリンクしますか?あなたの2番目の箇条書きには、クライアントへの応答ではまだ情報が利用可能ですが、応答の本体にはなく、ヘッダーに入っています。最後の段落で+1します。 –

5

同じヘッダーを追加することをお勧めします。メタデータをヘッダーに移動すると、result,dataまたはrecordsなどのエンベロープを取り除くのに役立ちます。レスポンス本文には必要なデータのみが含まれています。ページネーションリンクを生成する場合は、Linkヘッダーを使用することもできます。詳細について

HTTP/1.1 200 
    X-Pagination-Count: 100 
    X-Pagination-Page: 5 
    X-Pagination-Limit: 20 
    Content-Type: application/json 

    [ 
     { 
     "id": 10, 
     "name": "shirt", 
     "color": "red", 
     "price": "$23" 
     }, 
     { 
     "id": 11, 
     "name": "shirt", 
     "color": "blue", 
     "price": "$25" 
     } 
    ] 

を参照してください。次のrel =を省略するための適切な解決策になる、あなたの最初の箇条書きに

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

関連する問題