標準のJSON API応答形式?


697

APIからのJSON応答を構造化するための標準またはベストプラクティスはありますか?明らかに、すべてのアプリケーションのデータは異なるため、私が気にすることはあまりありませんが、必要に応じて「応答の定型文」に関心があります。私の意味の例:

成功したリクエスト:

{
  "success": true,
  "payload": {
    /* Application-specific data would go here. */
  }
}

失敗したリクエスト:

{
  "success": false,
  "payload": {
    /* Application-specific data would go here. */
  },
  "error": {
    "code": 123,
    "message": "An error occurred!"
  }
}

16
人々はおそらくSOAPから学んだので、それを再び構築することはないでしょう...
DenysSéguret12年

18
@dystroy:コメントを説明してください。
FtDRbwLXw6 2012年

5
最近、JSON APIを設計する必要があり、それらが応答形式を定義する標準であるかどうか疑問に思ったので、私はこの質問に本当に興味を持っていました。あなたのものは実際にはかなり見栄えがよく、標準が見つからない場合は使用する価値があります。提供された回答が実際に質問に対応していないのは残念です。
Alex

13
@Alex残念ながら、どこに行って基準がないためです。JSON自体の中だけでなく、JSONをRESTfulアプリケーションまたはその他の種類のアプリケーションで使用する方法に関しても。誰もが違うやり方をしています。ベストプラクティス(HTTP応答、有意義なパッケージ構造、システムで使用するためにデータを構造化することに目を向ける)を自由にたどることができますが、主要なディストリビューターであるすべての人は、他とは少なくとも1つの異なることを行っています。 ..標準はありませんし、標準もありそうもないので、しっかりしたものを構築し、自分に合うように構築します。
Norguard、2012年

5
@Norguardには標準があります(私の回答を参照してください)。実際、標準のいいところは、たくさんの選択肢があることです。-アンドリュー・タネンバウム
アダム・ゲント

回答:


640

はい、いくつかの標準があります(標準の定義には多少の自由があります)。

  1. JSON API -JSON APIは、応答だけでなく、リソースの作成と更新もカバーします。
  2. JSend-シンプルで、おそらくあなたはすでに何をしているか。
  3. OData JSONプロトコル -非常に複雑です。
  4. HAL -ODataに似ていますが、HATEOASのようなものを目指しています。

JSON API記述フォーマットもあります:

  • Swagger
    • JSONスキーマ(swaggerで使用されますが、スタンドアロンで使用することもできます)
  • JSONでのWADL
  • ラム
  • HATEOASは理論的には自己記述であるため、HAL です。

19
ありがとうございました。特にJSendはまさに私が探していたものです。それは私がやっていたことに似ていますが、私の方法にはなかったいくつかの利点があります。@公平に言えば、JSendも彼自身の答えに非常に近いです。
FtDRbwLXw6 2013年

8
特にエラー応答については、HTTP APIの RFCドラフトの問題の詳細も気に入っています
Pieter Ennes

1
多分あなたはcode.google.com/p/json-serviceを説明フォーマットリストに追加したいですか?
emilesilvis 2014

1
「Railsの推奨標準」というラベルは少々誇張されていると思います。これはプログラマーのソリューションの1つにすぎません。何がそれを「推奨標準」にしているのかわからない(特に宝石の人気を見る場合-多くの人々がこれをまったく使用していないように見えます)?私は個人的には、ステータスにHTTPヘッダーの代わりに応答本文を使用するため、ほとんどのRailsプログラマーがこのソリューションを推奨することはないと思います
Iwo Dziechciarow

2
Google JSON Style Guideも参考になります
MRodrigues

195

Google JSONガイド

成功応答の戻り data

{
  "data": {
    "id": 1001,
    "name": "Wing"
  }
}

エラー応答の戻り error

{
  "error": {
    "code": 404,
    "message": "ID not found"
  }
}

クライアントがJSの場合は、を使用if ("error" in response) {}してエラーの有無を確認できます。


13
まず、Google JSONガイドでは、一重引用符の代わりに二重引用符を使用することをお勧めしています。
rpozarickij

1
PlayJsonのようなサーバー側のJSON APIからこれを処理できるかどうかは、どちらでもかまいません。@Steelyのリンクが壊れています
Rhys Bradbury

3
失敗のリストを提供する必要があるエラー(検証の問題など)はどうですか?
Xeoncross

1
@Xeoncrossという単語のリンクをクリックするとerror、Googleのページでこの例が示されます
MI Wright

@Xeoncross次のように定義されたerror.errors []を使用して、障害のリストを返すことができます。「エラーに関する追加情報のコンテナ。サービスが複数のエラーを返す場合、errors配列の各要素は異なるエラーを表します。」おそらく、トップレベルのエラーには「リクエストの入力検証が失敗しました」と記載されており、errors []配列には、発生した特定の検証エラーごとに1つのエントリがあります。
James Daily、

130

私は事実上の標準が実際に浮上していなかったと思います(そして、決してないかもしれません)。しかし、とにかく、ここに私の見解があります:

成功したリクエスト:

{
  "status": "success",
  "data": {
    /* Application-specific data would go here. */
  },
  "message": null /* Or optional success message */
}

失敗したリクエスト:

{
  "status": "error",
  "data": null, /* or optional error payload */
  "message": "Error xyz has occurred"
}

利点:成功とエラーの両方で同じトップレベルの要素

欠点:エラーコードはありませんが、必要に応じてステータスを(成功または失敗)コードに変更するか、「コード」という名前の別の最上位アイテムを追加できます。


3
はい、jsonの解析にPOJOを使用している場合、これは正しい方法です。POJOを使用する場合は、静的な非動的なJSON形式が必要です。
LOG_TAG 2014

シンプルで要領を得ています。jsendはエラーと失敗を区別するため、私の意見ではjsendよりも優れています。
Josue Alexander Ibarra

1
私もこのパターンを使用していますが、単一の文字列ではなくメッセージの配列でmessagesあるというフィールドを使用しています。
StockBreak

4
答えは、よく文書化されたJSendのほぼコピーであり、シンプルで非常に便利です。これらはfail、典型的な検証問題の3番目のステータスを提供しますが、errordbエラーなどの致命的エラーでのみ使用されます。
s3m3n 2016年

成功のため:200ヘッダーにある場合、なぜstatusフィールドが必要なのですか?データオブジェクトを直接返すだけです。TypeScriptのような型付けされたFE言語では、これがさらに問題を引き起こす可能性があります。
Deniss M.

84

質問がREST Webサービスの設計に関するものであり、より正確には成功/エラーに関するものであるとします。

デザインは3種類あると思います。

  1. HTTPステータスコードのみを使用してエラーが発生したかどうかを示し、標準のエラーに制限します(通常はそれで十分です)。

    • 長所:APIに依存しない標準です。
    • 短所:実際に起こったことに関する情報が少ない。
  2. 使用する HTTPステータス+ json本文をます(エラーであっても)。エラー(コード、メッセージ、理由、タイプなど)の統一された構造を定義し、それをエラーに使用します。成功した場合は、予想されるjson応答を返します。

    • 長所:既存のHTTPステータスコードを使用し、エラーを説明するjsonを返すため、標準のままです(何が起こったかについての詳細情報を提供します)。
    • 短所:出力jsonは、エラーか成功かによって異なります。
  3. httpステータス(例:常にステータス200)を忘れて、常にjsonを使用し、応答のルートにブール値のresponseValidとエラーオブジェクト(コード、メッセージなど)を追加します。 (成功)が読み込まれます。

    • 長所:クライアントはjson文字列である応答の本文のみを処理し、status(?)を無視します。

    • 短所:あまり標準的ではありません。

選択するのはあなた次第です:)

APIに応じて、2または3を選択します(json REST APIには2を好みます)。REST Apiの設計で経験したもう1つのことは、各リソース(URL)のドキュメントの重要性です。パラメーター、本体、応答、ヘッダーなど+例です。

私はまた、(JAX-RS実装)+ジャージを使用するためにあなたをお勧めしますgenson(javaの/ JSONデータバインディングライブラリ)。genson + jerseyをクラスパスにドロップするだけで、jsonが自動的にサポートされます。

編集:

  • ソリューション2は実装が最も困難ですが、ビジネスエラーだけでなく例外も適切に処理できるという利点があり、初期の努力がより重要ですが、長期的には勝ちます。

  • ソリューション3はサーバー側とクライアントの両方で簡単に実装できますが、responseValid +エラーを含む応答オブジェクトに返すオブジェクトをカプセル化する必要があるため、あまり良くありません。


2
私は「エラーの均一な構造を定義する」などの同様の提案をするべきだと言っていますが、これはまさに私が求めていることです。その答えは、「いいえ、この構造に関して標準的またはベストプラクティスは存在しない」ということになると思います。
FtDRbwLXw6 2012年

7
レコードの場合:HTTPステータスコードはヘッダーではありません。
pepkin88 2015年

3
「応答はjsonではなくhtmlになります。」違う!htmlはエラー処理とは何の関係もありません。応答は、サポートするコンテンツタイプにすることができます。
オリゴフレン

2
@アレックスHTTPステータスコードは、HTTP応答のヘッダーのステータス行にある3桁のコードです。その行の後にはヘッダーフィールドがあり、口語的にはヘッダーとも呼ばれます。
pepkin88



19

以下は、Instagramが使用しているjson形式です

{
    "meta": {
         "error_type": "OAuthException",
         "code": 400,
         "error_message": "..."
    }
    "data": {
         ...
    },
    "pagination": {
         "next_url": "...",
         "next_max_id": "13872296"
    }
}

19

私はこれが標準であると主張するほど傲慢ではないので、「私が好む」形式を使用します。

私は簡潔な応答を好みます(/ articlesのリストを要求するとき、記事のJSON配列が必要です)。

私のデザインでは、ステータスレポートにHTTPを使用しています。200はペイロードのみを返します。

400はリクエストの何が問題かを示すメッセージを返します。

{"message" : "Missing parameter: 'param'"}

リターン404モデル/コントローラー/ URIが存在しない場合はます

私の側での処理でエラーが発生した場合、次のメッセージで501を返します。

{"message" : "Could not connect to data store."}

私が見てきたことから、かなりの数のREST風のフレームワークがこれらの線に沿っている傾向があります。

根拠

JSONはペイロード形式であることが想定されており、セッションプロトコルではありません。詳細なセッション風のペイロードの全体的なアイデアは、XML / SOAPの世界と、これらの肥大化した設計を作成したさまざまな誤った選択から来ています。すべてが大きな頭痛の種であることを認識した後、REST / JSONのすべてのポイントは、KISSを使用してHTTPを遵守することでした。私はどちらのJSendにもリモートで標準があるものはないと思います。特に、それらの間でより冗長なものはありません。XHRはHTTP応答に反応します。AJAXにjQueryを使用する場合(ほとんどの場合と同様)、try/ catchおよびdone()/ fail()コールバックを使用してエラーをキャプチャできます。JSONでステータスレポートをカプセル化することがそれ以上に便利であることがわかりません。


2
「JSONはペイロード形式です...」。いいえ、JSONはデータのシリアル化形式です。これを使用して、セッションプロトコルや単純なペイロードなど、必要なものを送信できます。あなたのKISSコメントは、JSONとは関係なく、的を射ています。JSONが何であるか(説明したように成功データまたは失敗理由データ)に焦点を合わせたままにしておくと、JSONを常に構成して後で削除する必要がある両方のマッシュマッシュで汚染するよりも優れています。その後、JSONデータをそのままCouchbaseに保存し、そのままアプリケーションに返すことができます。
Dirk Bester 2014

1
おそらく「ペイロード形式であると想定される」としてそれを定式化すべきだったのかもしれませんが、それとは別に、私のコメントを支持します。セッション/エラーデータをHTMLドキュメント内のbodyタグの属性として配置することもできますが、これは適切または適切な方法ではありません。
Bojan Markovic 2014

16

価値があることについては、これを別の方法で行います。呼び出しが成功すると、JSONオブジェクトのみが含まれます。trueを示す成功フィールドと、JSONオブジェクトを含むペイロードフィールドを含む、より高いレベルのJSONオブジェクトは必要ありません。ヘッダーのHTTPステータスに対して、200または200の範囲で適切なものを含む適切なJSONオブジェクトを返すだけです。

ただし、エラー(400ファミリーの何か)がある場合は、整形式のJSONエラーオブジェクトを返します。たとえば、クライアントがメールアドレスと電話番号を使用してユーザーをPOSTし、これらの1つが不正な形式である(つまり、基になるデータベースに挿入できない)場合、次のような結果を返します。

{
  "description" : "Validation Failed"
  "errors" : [ {
    "field" : "phoneNumber",
    "message" : "Invalid phone number."
  } ],
}

ここで重要なのは、「フィールド」プロパティは、検証できなかったJSONフィールドと正確に一致する必要があるということです。これにより、クライアントはリクエストの何が問題であったかを正確に知ることができます。また、「メッセージ」はリクエストのロケールにあります。「emailAddress」と「phoneNumber」の両方が無効な場合、「errors」配列には両方のエントリが含まれます。409(競合)JSON応答本文は次のようになります。

{
  "description" : "Already Exists"
  "errors" : [ {
    "field" : "phoneNumber",
    "message" : "Phone number already exists for another user."
  } ],
}

HTTPステータスコードとこのJSONを使用すると、クライアントは決定論的な方法でエラーに応答するために必要なすべてを備え、HTTPステータスコードを完全に置き換えようとする新しいエラー標準を作成しません。これらは400エラーの範囲でのみ発生することに注意してください。200の範囲にあるものについては、適切なものを返すだけです。私にとっては、HALのようなJSONオブジェクトであることがよくありますが、ここでは特に問題になりません。

追加について考えたのは、 "errors"配列のエントリまたはJSONオブジェクト自体のルートにある数値エラーコードです。しかし、今のところ必要はありません。


9

大きなソフトウェアジャイアント(Google、Facebook、Twitter、Amazonなど)の残りのAPI応答形式については合意していませんが、上記の回答には多くのリンクが提供されており、一部の人々は応答形式を標準化しようとしました。

APIのニーズは異なる可能性があるため、全員を参加させて特定の形式に同意することは非常に困難です。何百万人ものユーザーがAPIを使用している場合、なぜ応答形式を変更するのですか?

以下は、Google、Twitter、Amazon、およびインターネット上のいくつかの投稿に触発された応答形式に対する私の見解です。

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

Swaggerファイル:

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


1
エンベロープのないrest-api-response-formatへの
賛成票

@adnan kamilli->>> StatusCode:304、ReasonPhrase: 'Not Modified'、Version:1.1、Content:<null>、Headers:{} <<<<これはrestApiの適切な応答ですか?
アーノルドブラウン

@ArnoldBrown APIエンドポイント-アクションはこのコードを返しますか?
adnan kamili

画像(フォームデータ)のアップロードに使用されるAPIのレスポンスリターン-APIを記述したクライアント。
アーノルドブラウン

7

JSONのポイントは、JSONが完全に動的で柔軟であることです。これは、1つのノードをルートとするシリアル化されたJavaScriptオブジェクトと配列のセットにすぎないので、好きなように曲げてください。

ルートノードのタイプはあなた次第であり、ルートノードに含まれるものはあなた次第です。応答とともにメタデータを送信するかどうかは、mime-typeを設定するか、application/jsonそのままにするかtext/plainはあなた次第です(エッジケースの処理方法を知っている限り)。

好きな軽量スキーマを作成します。
個人的に、オンラインゲーミング用のアナリティクストラッキングとmp3 / ogg配信、イメージギャラリー配信、テキストメッセージングとネットワークパケット、ブログ投稿とブログコメントはすべて、何が何であるかに関して非常に異なる要件を持っていることがわかりました送信され、何が受信され、どのように消費されるべきか。

それで、私が望む最後のことは、それをすべて行うときに、それぞれをXML2.0などに基づく同じボイラープレート標準に準拠させることです。

そうは言っても、あなたにとって意味のある、よく考えられたスキーマを使用することについては多くのことが言われています
いくつかのAPI応答を読んで、好きなものを書き留め、好きでないものを批判し、それらの批判を書き留め、なぜ彼らが間違った方法でこすったのかを理解し、そしてあなたが学んだことをあなたが必要なものに適用する方法について考えてください。


1
返答ありがとうございます。繰り返しになりますが、ペイロード自体については心配していません。すべての例では、ペイロード内で何が送受信されるか、およびそれらのペイロードがどのように消費されるかに関して非常に異なる要件がありますが、それらはすべて、応答自体に関して同じ問題を解決する必要があります。つまり、要求が成功したかどうかをすべて確認する必要があります。そうであった場合、処理を続行します。そうでない場合、何が問題でしたか。私の質問で言及しているのは、すべての API応答に共通するのはこのボイラープレートです。
FtDRbwLXw6 2012年

すべてに対して200のステータスを返し、特定のエラーペイロードを自分で定義するか、またはペイロードの本文に詳細が含まれている(またはサポートされている場合)なしで、エラーに見合ったステータスを返します。私が言ったように、スキーマはあなた次第です-メタ/ステータス情報を含みます。それは、あなたが好む建築様式に基づいて、あなたが何をすべきかを行うための100%白紙の状態です。
Norguard、2012年

2
それは私が好きなように行うには白紙の状態であることに気づきました。私の質問の目的は、構造に関する限り、新しい標準があったかどうかを尋ねることです。「JSONとは何か、どのように使用するのか」ではなく、「JSONを使用して必要なものを返す/構造化する方法を知っていますが、標準の構造体が使用されているかどうかを知りたいのですが、人気になります。」質問を間違えたらすみません。とにかく、ご返信いただきありがとうございます。
FtDRbwLXw6 2012年

7

JSON-RPC 2.0は標準のリクエストとレスポンスのフォーマットを定義しており、REST APIを使用した後の新鮮な空気です。


JSON-RPC_2.0が例外に対して提供する唯一のものはエラーコードですか?数値エラーコードは、発生した問題を忠実に表すことはできません。
AgilePro

@AgilePro同意しました。数値エラーコードはあまりよくありません。仕様の作成者がcodeフィールドを文字列にすることを許可してくれれば幸いです。幸い、仕様により、エラーのdataフィールドに必要な情報を入れることができます。私のJSON-RPCプロジェクトでは、(標準プロトコルエラーの1つではなく)すべてのアプリケーション層エラーに対して、通常、単一の数値コードを使用します。次に、dataフィールドに詳細なエラー情報(実際のエラーの種類を示す文字列コードを含む)を入力します。
ドノー

2

後で来る人のために、HAL、JSend、JSON APIを含む承認された回答に加えて、調べる価値のある他のいくつかの仕様を追加します。

  • JSON-LDは、W3C勧告であり、JSONで相互運用可能なWebサービスを構築する方法を指定します
  • RESTのIon Hypermedia Type。「RESTのシンプルで直感的なJSONベースのハイパーメディアタイプ」と自称しています。

1

提案された基本的なフレームワークは問題ないように見えますが、定義されているエラーオブジェクトは非常に制限されています。多くの場合、問題を表すために単一の値を使用することはできず、代わりに一連の問題と原因が必要になります

少し調べてみたところ、エラー(例外)を返す最も一般的な形式は次の形式の構造であることがわかりました。

{
   "success": false,
   "error": {
      "code": "400",
      "message": "main error message here",
      "target": "approx what the error came from",
      "details": [
         {
            "code": "23-098a",
            "message": "Disk drive has frozen up again.  It needs to be replaced",
            "target": "not sure what the target is"
         }
      ],
      "innererror": {
         "trace": [ ... ],
         "context": [ ... ]
      }
   }
}

これは、OASISデータ標準OASIS ODataによって提案された形式であり、最も標準的なオプションのようですが、現時点では、どの標準の採用率も高くないようです。この形式は、JSON-RPC仕様に準拠しています。

これを実装する完全なオープンソースライブラリは、 Mendocino JSON Utilitiesにあります。このライブラリは、JSONオブジェクトと例外をサポートしています。

詳細は、JSON REST APIでのエラー処理に関する私のブログ投稿で説明されています。


0

常識以外に、法律違反や無法基準はありません。2人が話しているようにこれを抽象化する場合、標準は、最小の時間で最小の言葉でお互いを正確に理解できる最良の方法です。私たちの場合、「最小の単語」はトランスポート効率のために帯域幅を最適化し、「正確に理解する」はパーサー効率のための構造です。最終的にはデータが少なくなり、一般的な構造になります。ピンホールを通過し、共通のスコープで(少なくとも最初は)解析できるようにします。

提案されているほとんどすべてのケースで、私は「成功」と「エラー」のシナリオに対して別々の応答を目にしています。これら2つのケースで応答が異なる場合、なぜ本当に「成功」​​フラグをそこに置く必要があるのですか?「エラー」の欠如が「成功」であることは明らかではありませんか?「エラー」が設定された「成功」がTRUEである応答を持つことは可能ですか?または、「エラー」が設定されていない「成功」はFALSEですか?1つのフラグだけでは不十分ですか?「エラー」フラグは「成功」よりも「エラー」の方が少ないと思うので、「エラー」フラグのみを使用したいと思います。

また、本当に「エラー」をフラグにする必要がありますか?複数の検証エラーで応答したい場合はどうなりますか?したがって、各エラーをそのノードの子として持つ「エラー」ノードを作成する方が効率的です。空の(ゼロまで数える)「エラー」ノードは「成功」を示します。


-2

モバイル開発者が簡単に理解できるWeb APIのベストレスポンス。

これは「成功」応答用です

{  
   "ReturnCode":"1",
   "ReturnMsg":"Successfull Transaction",
   "ReturnValue":"",
   "Data":{  
      "EmployeeName":"Admin",
      "EmployeeID":1
   }
}

これは「エラー」応答用です

{
    "ReturnCode": "4",
    "ReturnMsg": "Invalid Username and Password",
    "ReturnValue": "",
    "Data": {}
}

2
プロパティを標準化することをお勧めします。これらはすべて「Return ...」の値です。ただし、データには接頭辞がありません。私は、すべての「Return」プレフィックスを削除すると思います。
z0mbi3

「Return」を含めることもかなり冗長です。
ジャックマルケッティ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.