标准的 JSON API 响应格式?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12806386/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Standard JSON API response format?
提问by FtDRbwLXw6
Do standards or best practices exist for structuring JSON responses from an API? Obviously, every application's data is different, so that much I'm not concerned with, but rather the "response boilerplate", if you will. An example of what I mean:
是否存在用于构建来自 API 的 JSON 响应的标准或最佳实践?显然,每个应用程序的数据都是不同的,所以如果您愿意的话,我不关心太多,而是“响应样板”。我的意思的一个例子:
Successful request:
请求成功:
{
"success": true,
"payload": {
/* Application-specific data would go here. */
}
}
Failed request:
失败的请求:
{
"success": false,
"payload": {
/* Application-specific data would go here. */
},
"error": {
"code": 123,
"message": "An error occurred!"
}
}
采纳答案by Adam Gent
Yes there are a couple of standards (albeit some liberties on the definition of standard) that have emerged:
是的,已经出现了一些标准(尽管在标准定义上有一些自由):
- JSON API- JSON API covers creating and updating resources as well, not just responses.
- JSend- Simple and probably what you are already doing.
- OData JSON Protocol- Very complicated.
- HAL- Like OData but aiming to be HATEOASlike.
- JSON API- JSON API 还涵盖创建和更新资源,而不仅仅是响应。
- JSend- 简单,可能是你已经在做的。
- OData JSON 协议- 非常复杂。
- HAL- 像 OData,但目标是像HATEOAS。
There are also JSON API description formats:
还有 JSON API 描述格式:
- Swagger
- JSON Schema(used by swagger but you could use it stand alone)
- WADL in JSON
- RAML
- HAL because HATEOASin theory is self describing.
- 昂首阔步
- JSON Schema(由 swagger 使用,但您可以单独使用)
- JSON 格式的 WADL
- 随机存取存储器
- HAL 因为理论上 HATEOAS是自我描述的。
回答by Steely Wing
Google JSON guide
谷歌 JSON 指南
Success response return data
成功响应返回 data
{
"data": {
"id": 1001,
"name": "Wing"
}
}
Error response return error
错误响应返回 error
{
"error": {
"code": 404,
"message": "ID not found"
}
}
and if your client is JS, you can use if ("error" in response) {}to check if there is an error.
如果你的客户端是JS,你可以用它if ("error" in response) {}来检查是否有错误。
回答by trungly
I guess a defacto standard has not really emerged (and may never). But regardless, here is my take:
我想事实上的标准还没有真正出现(并且可能永远不会出现)。但无论如何,这是我的看法:
Successful request:
请求成功:
{
"status": "success",
"data": {
/* Application-specific data would go here. */
},
"message": null /* Or optional success message */
}
Failed request:
失败的请求:
{
"status": "error",
"data": null, /* or optional error payload */
"message": "Error xyz has occurred"
}
Advantage: Same top-level elements in both success and error cases
优点:成功案例和错误案例中的顶级元素相同
Disadvantage: No error code, but if you want, you can either change the status to be a (success or failure) code, -or- you can add another top-level item named "code".
缺点:没有错误代码,但如果需要,您可以将状态更改为(成功或失败)代码,或者 - 您可以添加另一个名为“代码”的顶级项目。
回答by eugen
Assuming you question is about REST webservices design and more precisely concerning success/error.
假设您的问题是关于 REST 网络服务设计,更准确地说是关于成功/错误。
I think there are 3 different types of design.
我认为有 3 种不同类型的设计。
Use only HTTP Status codeto indicate if there was an error and try to limit yourself to the standard ones (usually it should suffice).
- Pros: It is a standard independent of your api.
- Cons: Less information on what really happened.
Use HTTP Status + json body(even if it is an error). Define a uniform structure for errors (ex: code, message, reason, type, etc) and use it for errors, if it is a success then just return the expected json response.
- Pros: Still standard as you use the existing HTTP status codes and you return a json describing the error (you provide more information on what happened).
- Cons: The output json will vary depending if it is a error or success.
Forget the http status(ex: always status 200), always use json and add at the root of the response a boolean responseValid and a error object (code,message,etc) that will be populated if it is an error otherwise the other fields (success) are populated.
Pros: The client deals only with the body of the response that is a json string and ignores the status(?).
Cons: The less standard.
仅使用HTTP 状态代码来指示是否存在错误,并尝试将自己限制为标准代码(通常就足够了)。
- 优点:它是独立于您的 api 的标准。
- 缺点:关于真正发生的事情的信息较少。
使用HTTP 状态 + json 正文(即使是错误)。为错误定义统一的结构(例如:代码、消息、原因、类型等)并将其用于错误,如果成功则返回预期的 json 响应。
- 优点:仍然是标准的,因为您使用现有的 HTTP 状态代码并返回一个描述错误的 json(您提供有关发生的事情的更多信息)。
- 缺点:输出 json 将根据是错误还是成功而有所不同。
忘记 http 状态(例如:始终状态 200),始终使用 json 并在响应的根添加一个布尔值 responseValid 和一个错误对象(代码、消息等),如果是错误则将填充该对象,否则其他字段(成功)被填充。
优点:客户端仅处理作为 json 字符串的响应正文,而忽略状态(?)。
缺点:标准较低。
It's up to you to choose :)
由你来选择:)
Depending on the API I would choose 2 or 3 (I prefer 2 for json rest apis). Another thing I have experienced in designing REST Api is the importance of documentation for each resource (url): the parameters, the body, the response, the headers etc + examples.
根据 API,我会选择 2 或 3(对于 json rest apis,我更喜欢 2)。我在设计 REST Api 时经历的另一件事是每个资源 (url) 文档的重要性:参数、正文、响应、标题等 + 示例。
I would also recommend you to use jersey (jax-rs implementation) + genson(java/json databinding library). You only have to drop genson + jersey in your classpath and json is automatically supported.
我还建议您使用 jersey(jax-rs 实现)+ genson(java/json 数据绑定库)。你只需要在你的类路径中删除 genson + jersey 并且自动支持 json 。
EDIT:
编辑:
Solution 2 is the hardest to implement but the advantage is that you can nicely handle exceptions and not only business errors, initial effort is more important but you win on the long term.
Solution 3 is the easy to implement on both, server side and client but it's not so nice as you will have to encapsulate the objects you want to return in a response object containing also the responseValid + error.
解决方案 2 最难实施,但优点是您可以很好地处理异常,而不仅仅是业务错误,最初的努力更重要,但从长远来看,您会获胜。
解决方案 3 在服务器端和客户端都很容易实现,但它不是很好,因为您必须将要返回的对象封装在包含 responseValid + 错误的响应对象中。
回答by Berislav Lopac
The RFC 7807: Problem Details for HTTP APIsis at the moment the closest thing we have to an official standard.
在RFC 7807:问题详细信息为HTTP的API是目前我们有一个正式的标准最接近。
回答by Muhammad Amin
Following is the json format instagram is using
以下是 instagram 使用的 json 格式
{
"meta": {
"error_type": "OAuthException",
"code": 400,
"error_message": "..."
}
"data": {
...
},
"pagination": {
"next_url": "...",
"next_max_id": "13872296"
}
}
回答by Bojan Markovic
I will not be as arrogant to claim that this is a standard so I will use the "I prefer" form.
我不会傲慢地声称这是一个标准,所以我将使用“我喜欢”的形式。
I prefer terse response (when requesting a list of /articles I want a JSON array of articles).
我更喜欢简洁的响应(在请求 /articles 列表时,我想要一个 JSON 文章数组)。
In my designs I use HTTP for status report, a 200returns just the payload.
在我的设计中,我使用 HTTP 进行状态报告,200只返回有效负载。
400returns a message of what was wrong with request:
400返回请求错误的消息:
{"message" : "Missing parameter: 'param'"}
Return 404if the model/controler/URI doesn't exist
如果模型/控制器/URI 不存在,则返回404
If there was error with processing on my side, I return 501with a message:
如果我这边处理出错,我会返回501并显示一条消息:
{"message" : "Could not connect to data store."}
From what I've seen quite a few REST-ish frameworks tend to be along these lines.
从我所看到的相当多的 REST 风格的框架来看,往往都遵循这些原则。
Rationale:
理由:
JSON is supposed to be a payloadformat, it's not a session protocol. The whole idea of verbose session-ish payloads comes from the XML/SOAP world and various misguided choices that created those bloated designs. After we realized all of it was a massive headache, the whole point of REST/JSON was to KISS it, and adhere to HTTP. I don't think that there is anything remotely standardin either JSend and especially not with the more verbose among them. XHR will react to HTTP response, if you use jQuery for your AJAX (like most do) you can use try/catchand done()/fail()callbacks to capture errors. I can't see how encapsulating status reports in JSON is any more useful than that.
JSON 应该是一种有效载荷格式,而不是会话协议。冗长的会话式有效负载的整个想法来自 XML/SOAP 世界和各种造成这些臃肿设计的误导选择。在我们意识到这一切都是一个令人头疼的问题之后,REST/JSON 的全部意义在于亲吻它,并坚持 HTTP。我认为JSend 中没有任何远程标准,尤其是其中更冗长的。XHR 将对 HTTP 响应做出反应,如果您将 jQuery 用于 AJAX(像大多数人一样),您可以使用try/catch和done()/fail()回调来捕获错误。我看不出在 JSON 中封装状态报告比这更有用。
回答by robert_difalco
For what it's worth I do this differently. A successful call just has the JSON objects. I don't need a higher level JSON object that contains a success field indicating true and a payload field that has the JSON object. I just return the appropriate JSON object with a 200 or whatever is appropriate in the 200 range for the HTTP status in the header.
为了它的价值,我以不同的方式这样做。成功的调用只有 JSON 对象。我不需要包含表示 true 的成功字段和具有 JSON 对象的有效负载字段的更高级别的 JSON 对象。我只是返回带有 200 或 200 范围内适合标头中 HTTP 状态的任何适当 JSON 对象。
However, if there is an error (something in the 400 family) I return a well-formed JSON error object. For example, if the client is POSTing a User with an email address and phone number and one of these is malformed (i.e. I cannot insert it into my underlying database) I will return something like this:
但是,如果出现错误(400 系列中的错误),我将返回一个格式良好的 JSON 错误对象。例如,如果客户端使用电子邮件地址和电话号码发布用户并且其中一个格式不正确(即我无法将其插入到我的基础数据库中),我将返回如下内容:
{
"description" : "Validation Failed"
"errors" : [ {
"field" : "phoneNumber",
"message" : "Invalid phone number."
} ],
}
Important bits here are that the "field" property must match the JSON field exactly that could not be validated. This allows clients to know exactly what went wrong with their request. Also, "message" is in the locale of the request. If both the "emailAddress" and "phoneNumber" were invalid then the "errors" array would contain entries for both. A 409 (Conflict) JSON response body might look like this:
这里的重要一点是“字段”属性必须与无法验证的 JSON 字段完全匹配。这使客户可以确切地知道他们的请求出了什么问题。此外,“消息”位于请求的语言环境中。如果“emailAddress”和“phoneNumber”都无效,则“errors”数组将包含两者的条目。409(冲突)JSON 响应正文可能如下所示:
{
"description" : "Already Exists"
"errors" : [ {
"field" : "phoneNumber",
"message" : "Phone number already exists for another user."
} ],
}
With the HTTP status code and this JSON the client has all they need to respond to errors in a deterministic way and it does not create a new error standard that tries to complete replace HTTP status codes. Note, these only happen for the range of 400 errors. For anything in the 200 range I can just return whatever is appropriate. For me it is often a HAL-like JSON object but that doesn't really matter here.
有了 HTTP 状态代码和这个 JSON,客户端就可以确定性地响应错误所需的一切,并且它不会创建一个新的错误标准来尝试完全替换 HTTP 状态代码。请注意,这些仅发生在 400 错误范围内。对于 200 范围内的任何内容,我都可以返回任何合适的内容。对我来说,它通常是一个类似 HAL 的 JSON 对象,但这在这里并不重要。
The one thing I thought about adding was a numeric error code either in the the "errors" array entries or the root of the JSON object itself. But so far we haven't needed it.
我想添加的一件事是在“错误”数组条目或 JSON 对象本身的根中的数字错误代码。但到目前为止,我们还不需要它。
回答by adnan kamili
Their is no agreement on the rest api response formats of big software giants - Google, Facebook, Twitter, Amazon and others, though many links have been provided in the answers above, where some people have tried to standardize the response format.
他们对谷歌、Facebook、Twitter、亚马逊等大型软件巨头的rest api响应格式没有达成一致,尽管上面的答案中提供了许多链接,有些人试图标准化响应格式。
As needs of the API's can differ it is very difficult to get everyone on board and agree to some format. If you have millions of users using your API, why would you change your response format?
由于 API 的需求可能不同,因此很难让每个人都参与进来并同意某种格式。如果您有数百万用户使用您的 API,为什么要更改响应格式?
Following is my take on the response format inspired by Google, Twitter, Amazon and some posts on internet:
以下是我对受 Google、Twitter、Amazon 和互联网上一些帖子启发的响应格式的看法:
https://github.com/adnan-kamili/rest-api-response-format
https://github.com/adnan-kamili/rest-api-response-format
Swagger file:
招摇文件:
回答by Norguard
The point of JSON is that it is completely dynamic and flexible. Bend it to whatever whim you would like, because it's just a set of serialized JavaScript objects and arrays, rooted in a single node.
JSON 的要点在于它是完全动态且灵活的。随心所欲地改变它,因为它只是一组序列化的 JavaScript 对象和数组,植根于单个节点。
What the type of the rootnode is is up to you, what it contains is up to you, whether you send metadata along with the response is up to you, whether you set the mime-type to application/jsonor leave it as text/plainis up to you (as long as you know how to handle the edge cases).
根节点的类型取决于您,它包含的内容取决于您,是否将元数据与响应一起发送取决于您,是将 mime-type 设置为application/json还是保持原样text/plain由您决定(只要你知道如何处理边缘情况)。
Build a lightweight schema that you like.
Personally, I've found that analytics-tracking and mp3/ogg serving and image-gallery serving and text-messaging and network-packets for online gaming, and blog-posts and blog-comments allhave very different requirementsin terms of what is sent and what is received and how they should be consumed.
构建您喜欢的轻量级架构。
就个人而言,我发现,分析,跟踪和MP3 / OGG服务和图像画廊服务和短信和网络数据包的网络游戏和博客,帖文,博客,评论都有着非常不同的要求在什么条件发送和接收的内容以及如何使用它们。
So the last thing I'd want, when doing all of that, is to try to make each one conform to the same boilerplate standard, which is based on XML2.0 or somesuch.
因此,在完成所有这些工作时,我最不想做的事情是尝试使每个模板都符合相同的样板标准,该标准基于 XML2.0 或类似标准。
That said, there's a lot to be said for using schemas which make sense to youand are well thought out.
Just read some API responses, note what you like, criticize what you don't, write those criticisms down and understand why they rub you the wrong way, and then think about how to apply what you learned to what you need.
也就是说,使用对您有意义且经过深思熟虑的模式有很多话要说。
只需阅读一些 API 响应,记下您喜欢什么,批评您不喜欢什么,写下这些批评并理解为什么它们会以错误的方式影响您,然后考虑如何将您学到的知识应用到您需要的内容中。

