web-dev-qa-db-ja.com

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

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

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

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

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

[
]

...それともメッセージとエラーコードの方がいいですか?

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

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

52
Andres SK

通常、結果のレコード数をメタデータとして返します。それが正常かどうかはわかりませんREST実践ですが、それはそれほど多くの追加データではなく、非常に正確です。通常、多くのサービスにページ分割があり、巨大な結果セットを返すことは現実的ではありませんすぐに。小さな結果セットのページ分割があると、私は困ります。それが空の場合、number_of_records : 0を返し、booksを空のリスト/配列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呼び出しを提供します。

47
grizwako

あなたの例は壊れています。重複するキーを持つjsonオブジェクトは必要ありません。あなたが探しているのはan arrayで、次のようなムービーオブジェクトがあります:

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

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

[]

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

105
Martin Wickman

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

したがって、レコードがある場合は、次のように返されます。

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

また、レコードがない場合は、次のように返されます。

    [

    ]
15

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

サーバーは要求を満たしていますが、エンティティ本体を返す必要はなく、更新されたメタ情報を返したい場合があります。応答には、エンティティヘッダーの形式で新しいメタ情報または更新されたメタ情報を含めることができます(存在する場合、要求されたバリアントに関連付ける必要があります)。

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

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

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

14
David Sergey

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

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

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

/v1/get/books(リソースを返さない)を呼び出すと、次が返されます。

{
    "books": []
}
10
Tim Blair

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

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

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

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

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

5
Vihung

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

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

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

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

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

5
The Spooniest

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

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

ここには「ベストプラクティス」はありません。どちらの例も任意であり、1つだけ選んで一貫性があるにします。開発者は驚きを嫌います。映画がないときに/v1/get/movies{}を返す場合、俳優がないときに/v1/get/actors{}を返すことを期待します。

3
yannis

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

3
devnull
  • まず最初に、URLにgetを含めることはRESTfulではなく、GETはHTTPメソッドによって暗黙的に指定されます。
  • GETapi/moviesのようなコレクションをリクエストする場合は、空の配列200 OKを含む[]を返します。
  • GETapi/movies/11はID)のような特定の映画をリクエストしていて、存在しない場合は、404 Not Foundを返します。

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

1
felixfbecker

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

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

ステータス204 +空のボディを返すように提案がありました。つまり、強制的にeverysingle clientにステータス204を正しく処理させます。さらに、JSON以外の返信を強制的に処理します。リクエストが応答を受け取ったからといって、httpが使用されたときにサーバーからの応答が返されたわけではなく、応答がJSONであることを確認するだけでこれらのケースの多くを処理できることを皆さんが理解していると思います。

1
gnasher729

厳密な答えはマークされているものではないと思います。

Nirthによって提供される答えは、真のRESTシナリオで最高です。ボディの応答は空で、httpステータスコード:204です。リソースは存在しますが、「コンテンツがありません」その時:は空です。

REST HTTP_Status_Codes

1
jmmtcarvalho

「それは場合によります」。

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

私の例の詳細については議論の余地があると思いますが、アイデアはわかります...

0
JohnB