将元数据添加到 RESTful JSON 响应的最佳实践是什么?

2022-09-01 00:12:26

背景

我们正在构建一个 Restful API,它应该将数据对象作为 JSON 返回。在大多数情况下,只需返回数据对象即可,但在某些情况下,f.ex.分页或验证,我们需要向响应添加一些元数据。

到目前为止,我们有什么

我们已经包装了所有json响应,如以下示例所示:

{
    "metadata" :{
        "status": 200|500,
        "msg": "Some message here",
        "next": "http://api.domain.com/users/10/20"
        ...
    },
    "data" :{
        "id": 1001,
        "name": "Bob"
    }
}

优点

  • 我们可以向响应中添加有用的元数据

缺点

  • 在大多数情况下,我们不需要元数据字段,这会增加json格式的复杂性。
  • 由于它不再是数据对象,而更像是包络响应,因此我们不能在不提取数据对象的情况下立即在f.ex骨干.js中使用响应。

问题

向 json 响应添加元数据的最佳做法是什么?

更新

到目前为止,我从下面的答案中得到的答案:

  • 删除返回 http 协议中的 http 响应代码 (200, 500 ...)metadata.status
  • 将错误消息添加到 http 500 repsonse 的正文中
  • 对于分页,我自然会有一些元数据来说明分页结构,以及嵌套在该结构中的数据
  • 可以将少量元数据添加到 http 标头(X-something)

答案 1

您可以通过多种方式在 RESTful API 中传递元数据:

  1. Http 状态代码
  2. 响应正文

对于 metadata.status,请使用 Http 状态代码,这就是用途!如果元数据引用整个响应,则可以将其添加为标头字段。如果元数据仅引用响应的一部分,则必须将元数据作为对象的一部分嵌入。不要将整个响应包装在人为的信封中,并将包装器拆分为数据和元数据。

最后,在整个 API 中与您所做的选择保持一致

一个很好的例子是带有分页的整个集合上的GET。GET /items 您可以在自定义标头中返回集合大小和当前页。和标准链接标题中的分页链接:

Link: <https://api.mydomain.com/v1/items?limit=25&offset=25>; rel=next

此方法的问题在于,当您需要添加引用响应中特定元素的元数据时。在这种情况下,只需将其嵌入到对象本身中即可。并有一个一致的方法...始终将所有元数据添加到响应中。因此,回到 GET /items,假设每个项目都已创建并更新了元数据:

{
  items:[
    {
      "id":"w67e87898dnkwu4752igd",
      "message" : "some content",
      "_created": "2014-02-14T10:07:39.574Z",
      "_updated": "2014-02-14T10:07:39.574Z"
    },
    ......
    {
      "id":"asjdfiu3748hiuqdh",
      "message" : "some other content",
      "_created": "2014-02-14T10:07:39.574Z",
      "_updated": "2014-02-14T10:07:39.574Z"
    }
  ],
  "_total" :133,
  "_links" :[
     {
        "next" :{
           href : "https://api.mydomain.com/v1/items?limit=25&offset=25"
         } 
   ]
}

请注意,集合响应是一种特殊情况。如果将元数据添加到集合中,则该集合不能再作为数组返回,它必须是包含数组的对象。为什么是对象?因为您要添加一些元数据属性。

与各个项目中的元数据进行比较。没有接近包装实体的内容。您只需向资源添加一些属性即可。

一种约定是区分控件或元数据字段。您可以在这些字段前面加上下划线。


答案 2

按照@Charlie的评论:对于您问题的分页部分,您仍然需要将元数据烘焙到响应somhow中,但是这里的和属性有些多余,因为它们已经被协议本身所覆盖(状态 - 找到模型,- 找不到模型,-不够的 privs,你明白了)(参见 spec)).即使您的服务器返回错误条件,您仍然可以将该部分作为响应正文发送。这两个字段将满足您的大部分元数据需求。statusmessageHTTP200404403message

就个人而言,我倾向于(ab)对较小的元数据片段(带有前缀)使用自定义HTTP标头,但我想这种不切实际的限制非常低。X-

我已经在一个范围较小的问题中对此进行了一些扩展,但我认为这些观点对于这个问题仍然有效。