标准的JSON API响应格式?

时间:2012-10-09 18:43:36

标签: json request response

是否存在用于从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!"
  }
}

17 个答案:

答案 0 :(得分:557)

是的,已经出现了一些标准(尽管对标准的定义有一些自由):

  1. JSON API - JSON API还包括创建和更新资源,而不仅仅是响应。
  2. JSend - 很简单,也许你正在做的事情。
  3. OData JSON Protocol - 非常复杂。
  4. HAL - 与OData一样,但目标是HATEOAS喜欢。
  5. 还有JSON API描述格式:

答案 1 :(得分:161)

Google JSON guide

成功回复data

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

错误回复返回error

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

如果您的客户端是JS,您可以使用if ("error" in response) {}检查是否有错误。

答案 2 :(得分:104)

我猜一个事实上的标准并没有真正出现(也许永远不会)。 但无论如何,这是我的看法:

成功请求:

{
  "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 :(得分:75)

假设您对REST Web服务设计有疑问,更准确地说是成功/错误。

我认为有3种不同类型的设计。

  1. 使用仅HTTP状态代码来指示是否存在错误并尝试将自己限制为标准错误(通常应该足够)。

    • 优点:这是一个独立于你的api的标准。
    • 缺点:关于真实情况的信息较少。
  2. 使用 HTTP状态+ json正文(即使是错误的)。为错误定义统一的结构(例如:代码,消息,原因,类型等)并将其用于错误,如果成功则返回预期的json响应。

    • 优点:当您使用现有的HTTP状态代码时仍然是标准的,并返回描述错误的json(您提供有关所发生情况的更多信息)。
    • 缺点:输出json会因错误或成功而异。
  3. 忘记http状态(例如:总是状态200),总是使用json并在响应的根处添加一个布尔值responseValid和一个错误对象(代码,消息等)如果是错误,将填充,否则填充其他字段(成功)。

    • 优点:客户端仅处理作为json字符串的响应主体并忽略状态(?)。

    • 缺点:标准较低。

  4. 由您决定:)

    根据API,我会选择2或3(我更喜欢2为json rest apis)。 我在设计REST Api时遇到的另一件事是每个资源(url)的文档的重要性:参数,正文,响应,标题等+示例。

    我还建议你使用jersey(jax-rs实现)+ genson(java / json数据绑定库)。 您只需在类路径中删除genson + jersey并自动支持json。

    修改

    • 解决方案2是最难实现的,但优势在于您可以很好地处理异常,而不仅仅是业务错误,初始工作更重要,但您可以长期获胜。

    • 解决方案3很容易在服务器端和客户端上实现,但它不是很好,因为你必须在响应对象中封装你想要返回的对象,同时包含responseValid +错误。

答案 4 :(得分:19)

我不会傲慢地声称这是一个标准,所以我将使用“我更喜欢”的形式。

我更喜欢简洁的回应(在请求/文章列表时,我想要一个JSON数组文章)。

在我的设计中,我使用HTTP进行状态报告, 200 仅返回有效负载。

400 会返回有关请求错误的消息:

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

如果模型/控制器/ URI不存在,则返回 404

如果处理中出现错误,我会返回 501 并显示一条消息:

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

从我所看到的,很多REST-ish框架都倾向于沿着这些方向发展。

<强>原理

JSON应该是有效载荷格式,它不是会话协议。详细的session-ish有效载荷的整个想法来自XML / SOAP世界以及创建那些臃肿设计的各种错误选择。在我们意识到所有这一切都是一个巨大的问题之后,REST / JSON的重点就是KISS,并坚持使用HTTP。我不认为JSend中有任何远程标准,尤其是其中没有更详细的内容。 XHR将对HTTP响应作出反应,如果您为AJAX使用jQuery(与大多数人一样),您可以使用try / catchdone() / fail()回调来捕获错误。我无法看到JSON中的封装状态报告如何比这更有用。

答案 5 :(得分:17)

以下是json格式的instagram正在使用

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

答案 6 :(得分:15)

对于它的价值我不同地做到这一点。成功调用只有JSON对象。我不需要更高级别的JSON对象,其中包含指示true的成功字段和具有JSON对象的有效负载字段。我只返回适当的JSON对象,其中包含200或200范围内适用于标题中HTTP状态的任何内容。

但是,如果出现错误(400系列中的某些内容),我将返回格式正确的JSON错误对象。例如,如果客户端使用电子邮件地址和电话号码对用户进行POST,并且其中一个格式不正确(即我无法将其插入到我的基础数据库中),我将返回以下内容:

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

这里的重要部分是“field”属性必须与无法验证的JSON字段完全匹配。这允许客户确切地知道他们的请求出了什么问题。此外,“message”位于请求的区域设置中。如果“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对象,但这并不重要。

我想添加的一件事是“错误”数组条目中的数字错误代码或JSON对象本身的根。但到目前为止我们还没有需要它。

答案 7 :(得分:14)

RFC 7807: Problem Details for HTTP APIs目前是我们对官方标准最接近的事情。

答案 8 :(得分:9)

他们对大型软件巨头谷歌,Facebook,Twitter,亚马逊等公司的其他api响应格式没有达成一致,尽管上面的答案中提供了很多链接,有些人试图将响应格式标准化。

由于API的需求可能不同,因此很难让所有人加入并同意某种格式。如果您有数百万用户使用您的API,为什么要更改您的响应格式?

以下是我对Google,Twitter,亚马逊以及互联网上的一些帖子启发的响应格式的看法:

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

Swagger文件:

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

答案 9 :(得分:7)

JSON的观点是它完全动态且灵活。将它弯曲到您想要的任何想法,因为它只是一组序列化的JavaScript对象和数组,以单个节点为根。

根节点的类型取决于您,它包含的内容取决于您,无论您是否将响应发送给您,是否将mime-type设置为application/json或保留text/plain取决于您(只要您知道如何处理边缘情况)。

构建您喜欢的轻量级架构 就个人而言,我发现分析跟踪和mp3 / ogg服务和图像库服务以及用于在线游戏的文本消息和网络数据包,以及博客帖子和博客评论所有都有< strong> 非常不同的要求 就发送内容和接收内容以及如何使用它们而言。

因此,在完成所有这些工作时,最后我想要的是尝试使每个符合相同的样板标准,该标准基于XML2.0或其他一些。

那就是说,使用对 有意义的架构并且经过深思熟虑有很多话要说。
只需阅读一些API回复,记下你喜欢什么,批评你不喜欢的东西,写下那些批评,理解为什么他们用错误的方式揉搓你,然后思考如何将你学到的东西应用到你需要的东西。

答案 10 :(得分:5)

JSON-RPC 2.0定义了标准的请求和响应格式,在使用REST API之后,这是一种新鲜空气。

答案 11 :(得分:2)

对于以后的内容,除了公认的答案(包括HAL,JSend和JSON API)之外,我还要添加一些其他值得研究的规范:

  • JSON-LD,这是W3C建议书,指定如何在JSON中构建可互操作的Web服务
  • Ion Hypermedia Type for REST,它声称自己是“ REST的一种简单直观的基于JSON的超媒体类型”

答案 12 :(得分:1)

我曾经遵循这个标准,在客户端层非常好,简单且干净。

通常,HTTP 状态为 200,这是我在顶部使用的标准检查。我通常使用以下 JSON

我也使用 API 的模板

dynamic response;

try {
   // query and what not.
   response.payload = new {
      data = new {
          pagination = new Pagination(),
          customer = new Customer(),
          notifications = 5
      }
   }

   // again something here if we get here success has to be true
   // I follow an exit first strategy, instead of building a pyramid 
   // of doom.
   response.success = true;
}
catch(Exception exception){
   response.success = false;
   response.message = exception.GetStackTrace();
   _logger.Fatal(exception, this.GetFacadeName())
}

return response;

{ 
  "success": boolean,
  "message": "some message",
  "payload": { 
     "data" : []
     "message": ""
     ... // put whatever you want to here.
  } 
}

在客户端层,我将使用以下内容:

if(response.code != 200) { 
  // woops something went wrong.
  return;
}

if(!response.success){
  console.debug ( response.message ); 
  return;
}

// if we are here then success has to be true.
if(response.payload) {
  ....
}

请注意我是如何早早突破以避开厄运金字塔的。

答案 13 :(得分:0)

建议的基本框架看起来不错,但是定义的错误对象太有限。人们通常不能使用单个值来表达问题,而只能使用chain of problems and causes is needed来表达问题。

我做了一些研究,发现返回错误(异常)的最常见格式是这种形式的结构:

{
   "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对象以及异常。

有关详细信息,请参见我在Error Handling in JSON REST API上的博客文章

答案 14 :(得分:0)

关于第二个示例,the JSON specification forbids it

  

成员数据和错误不得共存于同一文档中。

答案 15 :(得分:0)

除了常识之外,没有违法或违法标准。如果我们像两个人一样讲抽象,那么标准就是他们可以在最短的时间内用最少的单词准确理解彼此的最佳方式。在我们的案例中,“最少的字眼”是为提高传输效率而优化带宽,而“准确理解”是解析器效率的结构。最终最终得到的数据越少,结构越常见;这样它就可以穿过一个针孔,并可以通过一个通用示波器(至少在最初使用)进行解析。

几乎在所有建议的情况下,我都会对“成功”和“错误”场景分别做出回应,这对我来说有点模棱两可。如果在这两种情况下的响应不同,那么为什么我们真的需要在此处放置“成功”标志?缺少“错误”是否是“成功”,这不是很明显吗?是否可能在“成功”为TRUE且设置了“错误”的情况下进行响应?还是说,“成功”为FALSE,而未设置“错误”?仅一个标志是不够的?我宁愿只使用'Error'标志,因为我相信'Error'比'Success'少。

此外,我们是否真的应该将'Error'标记为?如果我想回答多个验证错误怎么办?因此,我发现拥有一个“错误”节点并将每个错误作为该节点的子节点更为有效;空的(错误计数为零)“错误”节点表示“成功”。

答案 16 :(得分:-1)

可轻松为移动开发人员理解的网络api最佳响应。

这是针对“成功”响应

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

这是针对“错误”响应

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