RESTful APIデザイン。行がない場合、何を返す必要がありますか?


50

現在、Slim Frameworkを使用してソーシャルネットワーク用のAPIをコーディングしています。私の質問は、json構造に返す行がない場合のベストプラクティスは何ですか?

この呼び出し/ v1 / get / moviesがテーブルmovie namesから2行を返すとしましょう

[
    {"name": "Ghostbusters"},
    {"name": "Indiana Jones"}
]

しかし、それから/ v1 / get / booksを呼び出すと、そのテーブルには行がありません。空の構造を返すだけですか?

[
]

...または、メッセージとエラーコードの方が良いでしょうか?

[
    "errors": {
        "message": "no matches found",
        "code": 134
    }
]

どちらが良い方法ですか?(APIはiOSおよびAndroidアプリで使用されます)ありがとう!


3
私にとって、これはゼロが実際に量であるかどうかの質問のように感じます。
スカーフリッジ

16
あなたの例は壊れています。重複キーを持つjsonオブジェクトを作成することはできません。あなたが探していることは、配列、すなわちです[{"name": "..."}, {"name":"..."}]
マーティンWICKMAN

@MartinWickmanすみません、直しました。
アンドレスSK

8
@andufo、実際に、あなたはしませんでした...
avakar

25
アプリケーションがRESTfulである場合、動詞/メソッドがエンドポイントURIの一部を「取得」するのはなぜですか?
user50849

回答:


46

通常、結果のレコード数をメタデータとして返します。それが通常のRESTプラクティスであるかどうかはわかりませんが、余計なデータではなく、非常に正確です。通常、多くのサービスにページネーションがあり、一度に巨大な結果セットを返すことは実用的ではありません。個人的には、小さな結果セットのページネーションがあるといらいらします。それが空の場合は、number_of_records : 0空のリスト/配列として本を返しbooks : []ます。

{
    meta: {
        number_of_records : 2,
        records_per_page : 10,
        page : 0
    },
    books : [
        {id:1},
        {id:27}
    ]
}

編集(数年後):マーティン・ウィックマンからの回答ははるかに優れています。ここに、理由の「短い」説明があります。

ページネーションを扱うときは、コンテンツまたは順序が変わる可能性を常に念頭に置いてください。たとえば、最初のリクエストが来ると、24件の結果が返され、最初の10が返されます。その後、「新しい本」が挿入され、現在25件の結果がありますが、元のリクエストでは10位で注文されます。最初のユーザーが2ページ目をリクエストしても、「新しい本」は取得されません。このような問題を処理する方法があります。たとえば、次のAPI呼び出しで送信される「リクエストID」を提供し、「古い」結果セットから次のページを返します。別の方法は、「最初の要求以降に変更された結果リスト」などのフィールドを追加することです。

一般に、可能であれば、余分な労力をかけてページネーションを避けてください。ページネーションは変更可能な追加の状態であり、サーバーとクライアントの両方がそれを処理する必要があるため、そのような変更の追跡はエラーが発生しやすくなります。

一度に処理するデータが多すぎる場合は、そのリストの一部のすべての結果と詳細を含む「idリスト」を返し、multi_get / get_by_id_list API呼び出しをリソースに提供することを検討してください。


1
ええ、なぜこの1つが他の1つほど高く投票されないのだろうか。特別な条件なしで盲目的に反復できる空のリスト(これはリストであるはずです)の両方を提供しているので、私はこれがより好きですが、メタデータも「いいえ、そうしません」エラーを無視してください。実際には結果はありませんでした」。
イズカタ

1
-1 booksパラメーターはオブジェクトですが、「books」は複数を意味し、複数は配列を意味するため。メタデータはクールで、最終的にはすべての書籍のコレクションが書籍オブジェクトの配列になると期待しています。本がない場合は、空の配列を教えてください
Charles Sprayberry

9
これに関する問題は、「number_of_records」を追加してもそれ以上の情報が提供されず、単に冗長性が追加され、複雑さが増すことです。エラーを通知するには、適切なhttpコード+本体に何かを返します。
マーティンウィックマン

1
@cspray booksは、Izkataが指摘したように、私のタイプミスです。
グリズワコ

2
@MartinWickman余分なメタデータで元の回答を汚染したくはありませんでしたが、私の経験では、多くのサービスがすべてのデータをすぐに返すのではなく、「ページ分割された」方法で返します。
グリズワコ

105

あなたの例は壊れています。重複キーを持つjsonオブジェクトを使用しないでください。あなたが探しているのは、次のようなムービーオブジェクトの配列です:

 [
    {"name": "movie1"}, 
    {"name": "movie2"}
 ]

このアプローチはあなたの質問にも答えます。クエリが一致しない場合、空の配列を返す必要があります

[]

一方、特定の映画リソースを取得しようとしてGET api/movie/34その映画が存在しない場合は、本文に適切な(jsonエンコードされた)エラーメッセージを含む404を返します


1
+1これはによる有効なJSONですjson_xs
l0b0

15

これがJSONの場合、オブジェクトの配列を返すことを本当に検討する必要があります。これには、レコードがない場合に空の配列になるなど、多くの利点があります。

したがって、レコードがある場合、次のように戻ります。

    [
        {"name": "Ghostbusters"},
        {"name": "Indiana Jones"}
    ]

そして、あなたが記録を持っていないとき、あなたは戻ってくるでしょう:

    [

    ]

14

操作を正常に実行しても、空のマップ{}や空の配列など、返すものが何もない[]場合、204応答コードで応答することをお勧めします。HTTPステータスコード定義仕様からの抜粋を次に示します

サーバーは要求を実行しましたが、エンティティ本体を返す必要はなく、更新されたメタ情報を返したい場合があります。応答には、エンティティヘッダーの形式で新しいメタデータまたは更新されたメタ情報が含まれている場合があります。

クライアントがユーザーエージェントである場合、リクエストの送信を引き起こしたドキュメントビューからドキュメントビューを変更すべきではありません。この応答は主に、ユーザーエージェントのアクティブなドキュメントビューを変更せずにアクションの入力を許可することを目的としていますが、新規または更新されたメタ情報は、ユーザーエージェントのアクティブビューに現在あるドキュメントに適用される必要があります。

204応答にはメッセージ本文を含めてはならない(MUST NOT)ため、ヘッダーフィールドの後の最初の空行で常に終了します。

基本的に、返すものがない場合は、HTTPを介したRESTfulアプリケーションで204を使用することをお勧めします。


4
ここの他の回答に関する@avakarのコメントに同意します。クライアントが/ v1 / get / movies / 1にアクセスしようとすると、1で識別できる映画がない場合は404を返します。映画がない場合でも、/ v1 / get / moviesだけで200を返します。ただし、204は入力アクションを対象としているため、適切ではありません。
imel96

7
このソリューションのもう1つの問題は、通常クライアントに特別なコードが必要になることです。応答が空のリストの場合、通常の応答と同様にJSONとして解析できます。応答が空のボディである場合、JSONパーサーは文句を言うでしょう(空のドキュメントは有効なJSONではないため)。したがって、クライアントはHTTP 204をチェックして解析をスキップするための追加のコードを必要とします。
sleske 14

7
これは、204の意図を誤解していると思います。204は、コンテンツを期待して何も見つけられなかった操作ではなく、成功して意図したリターンを持たない操作を意図しているようです。ウィキペディアから:「サーバーはリクエストを正常に処理しましたが、コンテンツを返していません。通常、削除リクエストの成功に対する応答として使用されます。」
XML 14

10

標準化されたJSON API形式の作成については、かなりの量の作業が行われています

その仕様の原則に従うことは、返されるすべてのリソースが事実上「コレクション」であることを意味します(単一のリソースのみが含まれている場合でも)。これに従うと、次の呼び出し/v1/get/moviesが返されます。

{
    "movies": [
        {"name": "Ghostbusters"},
        {"name": "Indiana Jones"}
    ]
}

/v1/get/books(ゼロリソースを返す)への呼び出しは以下を返します。

{
    "books": []
}

5

具体的な例として、/ v1 / get / booksが空の配列でHTTP 200を返すことをお勧めします。

あなたの投稿を読んでいる場合、APIは本を収集するつもりです。比phor的に言えば、本用の本棚、映画用のDVDラック、そしておそらくここで言及していない他のコンテナがあります。本を収集するため、/ v1 / get / booksが本棚です。これは、有効なリソース(書籍のリスト)があり、特定の例ではたまたま空であることを意味します。

この場合にHTTP 404を返すことをお勧めしないのは、本棚がまだあるからです。現時点では本はありませんが、まだ本棚です。それはAPI -if本棚は例-のために、収集図書に意図していないされていない場合は、その後 HTTP 404を適切であろう。しかし、そこにリソースがあるので、HTTP 404が行うリソースがないことを知らせるべきではありません。したがって、空の配列(コレクションを表す)を持つ200の方が適切であると主張します。

HTTP 204を返すことを推奨しない理由は、「コンテンツなし」が通常の状態であることを示唆するからです。このリソースでこのアクションを実行しても、通常は何も返されません。そのため、通常はDELETEリクエストへの応答として通常使用されます。たとえば、削除の性質は通常、返すものが何もないことを意味します。If-Modifiedファミリーのヘッダーでリクエストに応答するために使用される場合も同様です。リソースが変更された場合のみコンテンツが必要ですが、変更されていないため、コンテンツは提供しません。

しかし、空だが有効なコレクションを取得するためには、HTTP 204は意味をなさないと私は主張します。コレクションにアイテムがある場合、適切な表現はそのデータの配列になります。したがって、そこにデータがない場合(ただし、コレクションは有効)、適切な表現は空の配列です。


5

あなたは本当に2つのことのうちの1つだけをするべきです

200 (OK)本体にステータスコードと空の配列を返します。

または、204 (NO CONTENT)ステータスコードを返し、応答本文を返しません。

私にとって、オプション2はより技術的に正しく、RESTおよびHTTPの原則に沿っているようです。

ただし、オプション1はクライアントにとってより効率的です。クライアントは、2つの(成功)ステータスコードを区別するための特別なロジックを必要としないためです。常に配列を受け取ることを知っているので、アイテムがないか、1つ、または多くのアイテムがあるかどうかを確認し、適切に処理するだけです。


3

実稼働環境で両方のケースを見てきました。どちらを選択するかは、APIを使用するユーザーによって異なります。リストが空である理由を知りたい場合、またはリストが本当に空であり、リストの取得中にエラーが発生していないことを確認したい場合は、「エラー」オブジェクトを添付する必要があります。気にしない場合は、空のリストを返します。最初のアプローチよりも多くのニーズをカバーするため、2番目のアプローチを採用します。


3

RESTful APIを構築しているため、最初に考慮すべきことは、適切な応答コードを返すことです。そして、リクエストが正常に通過したが、リクエストされたリソースが現時点では利用できないことを伝えるためのより適切な応答コードは、由緒ある404です。

常に適切な応答コードを返すようにAPIを設計する場合、リソースが見つからなかったときに本文を返す必要すらありません。とはいえ、身体、特に人間が読めるものを返すことは害にはなりません。

ここには「ベストプラクティス」はありません。どちらの例もarbitrary意的であり、どちらかを選択して一貫性を保つだけです。開発者は驚きを嫌い/v1/get/moviesます。{}映画がないときに戻ってきたら、俳優がいないときに/v1/get/actorsも戻ってくると思い{}ます。


1
404を返すのは本当に正しいことですが、残念ながら、実際に誰もそれを行いません。
RibaldEddie

1
複雑な応答があり、それらの一部のみが空の場合、404を返すとユーザーが混乱します。
devnull

5
404メッセージには同意しません。404「リソースが存在しない」と解釈し、URLなどで問題が発生したかどうかを心配します。映画のリストを要求して404を取得した場合、映画のリソースはまったくないと思います。「204 No Content」がより適切な場合があります。
トールステンミュラー

8
わかりました、「ボディなし」の事はそれを殺すでしょう。しかし、「4xxクラスのステータスコードは、クライアントが誤っているように思われる場合を対象としています。」しかし、クライアント側でエラーはありませんでした。したがって、404は間違った情報を提供します。本文なしで204を送信するか、問題ないと言って空のリストを送信します。
トールステンミュラー

9
本のリストを要求している場合、404を返すということは、リストが空ではなく、リストが存在しないことを意味します。空のリストとともに200を返すことは、私にとって唯一の合理的なオプションのようです。
avakar

1

厳密な答えがマークされているとは思いません。

真のRESTシナリオでは、nirthが提供する答えが最適です。本文の応答は空で、httpステータスコード:204; リソースは存在しますが、その時点では「コンテンツがありません」:空です。

REST HTTP_Status_Codes


1

APIのすべてのクライアントによる処理が簡単になるため、200 +空の配列をお勧めします。200 +配列は、「そこにあるすべてのデータを返しました」という意味です。データを配信するコードとそれを処理するコードの両方で、アイテムの数は関係ありません。

他のすべてのステータスコードは、サーバーで適切に文書化および配信され、クライアントで適切に処理される必要があります。

ステータス204 +空のボディを返す提案がありました。手段は、あなたが強制的にそのすべての 単一正しくプロセスステータス204にクライアントを。さらに、JSON以外の応答を処理するように強制します!リクエストに答えがあったからといって、httpを使用したときにサーバーから答えが返されたわけではなく、レスポンスがJSONであることを確認するだけで、これらのケースの多くが処理されることを誰もが理解することを願っています。


0

私は「それは依存します」。

ゼロが妥当な結果である場合、空のリストを返します。たとえば、「bob」と呼ばれるすべての従業員を取得したい場合、「none」は非常に合理的な結果です。予期した結果ではない場合、エラーを返します。たとえば、雇用している人の住所の履歴リストを取得します。彼らはどこかに住んでいる必要があるため、通常の状態だけでなく、おそらくエラーではありません。

あなたは私の例の詳細について議論することができると確信していますが、あなたはアイデアを得る...


0
  • まずget、URLにRESTfulを含めることはできません。GETはHTTPメソッドによって暗示されます。
  • 空の配列でGET api/moviesa 200 OKを返すようなコレクションを要求している場合[]
  • GET api/movies/11idはどこにあるか)のような特定の映画をリクエストしていて、それが存在しない場合は、を返します404 Not Found

どうして?リソースをリクエストしてます。コレクションを要求しているとき、リソース自体(コレクション)が存在します。そのため、a 404は間違っています。ただし、特定の映画をリクエストしても存在しない場合、リクエストされたリソースは存在しないため、を返す必要があります404


-2

JSONを返す場合は、常にカウントとエラーメッセージを返し、エラーがあるかどうかを示すブール値を返すことをお勧めします。これは、各行のリストで返される標準の3つのメタ値です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.