在RESTful API中将数组作为响应返回的最佳方法是什么?


40

假设我们有这样的资源,

book:
    type: object
    properties:
        author: {type: string}
        isbn: {type: string}
        title: {type: string}

books:
    type: array
    items: book

因此,当某人GET在books资源上做出“ a” 时,我们将返回以下内容

[{"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},
 {"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}]

我从某个工作人员那里听说,建议的REST做法是始终将响应作为JSON对象返回,这意味着我们的架构应books如下所示,

books:
    type: object
    properties:
        list:
            type: array
            items: book

所以,现在,响应看起来像这样,

{
    "list": [{"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},
             {"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}]
}

以下哪项是最佳的REST实践?


1
JSON RESTful吗?您应该确定返回html吗?
伊万2015年

3
@Ewan:有效负载无关紧要。这就是MIME类型的用途。
罗伯特·哈维

1
REST都不是最佳实践。REST由HATEOAS组成,这意味着您的API具有可发现性。查找HAL或JSON-LD。
Florian Margaine 2015年

JSON-LD:慢慢地工作它的方式对WCF
伊万

从我读到的内容来看,对象内部包装的JSON数组是针对旧浏览器中报告的漏洞(haacked.com/archive/2009/06/25/json-hijacking.aspx)的一种防御措施。这似乎在当今的现代浏览器中已得到解决。比抱歉,我猜更好的安全..
Gishu

Answers:


35

在实践中,第二种选择是最佳实践。原因是仅返回数组时根本无法扩展资源。

例如:如果您需要添加所有记录的计数,则已经完成了“仅数组”方法。

如果在一个列表api中发生这种情况,那么您要使其保持一致,从而使所有对象成为一体,则您的api将变得更加一致,并且更易于开发人员使用。

例如:假设开发人员编写通用代码来使用您的api来显示列表和详细信息页面。他不想建立异常,因为有时是数组,有时是具有list属性的对象。

总的来说,这个答案与有关休息,仇恨和其他协议的原则无关,而只是关于需要发送给客户的数据的真实性。如果您决定跟随例如仇恨者,那么偏离路线就必须遵循他们的标准(也是对象)。


3
+1表示“关于数据的真实存在”(并且仍然意识到REST有一个更技术,更准确的定义)。
threed

8

[{"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},{"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}]

{
    "list": [{"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},
         {"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}]
}

是有效的杰森。我认为如果不需要它,您不应该添加“列表”,这甚至可能会造成混淆,因为其后的是数组而不是列表。

最佳REST做法?API应该对Accept标头中设置的内容做出正确的响应,并提供良好的文档。


7

之所以使您的响应符合JSON,是因为JSON是事实上的标准;带有JSON解析器的任何语言都可以轻松解析它,并且,如果您使用的是JavaScript,由于JavaScript本身就可以理解它,因此您甚至不需要解析器。

换句话说,使其与JSON兼容,您将不必编写自己的解析器。此外,当下一个开发人员编写使用该服务的软件时,也不会感到惊讶。

REST与您的JSON模式无关。从REST的角度来看,任何一种模式都是可以接受的。


9
这能回答问题吗?我将其读取为“我应该使用json数组还是json对象作为根?”。两者都可以使用json解析器进行解析,因此您的回答并不能帮助他们做出决定。
CodesInChaos

那没关系。我已经更新了答案。
罗伯特·哈维

如果我们谈论的是REST,那么该架构并不重要,只要它能够提供超媒体控件,使其仅基于响应而无需其他带外信息即可发现和操纵更多资源... OP提到的所有格式似乎都没有。
toniedzwiedz 2015年

...and if you're using JavaScript, you don't even need a parser since JavaScript understands it natively.好,是的,不是。JSON是JavaScript的子集,但是调用eval而不是使用解析器会立即使您容易受到包含恶意代码的“ JSON”的影响,并且解析很可能比以往任何时候都更有效率eval
2015年

5

具有单个无意义的键“列表”和数组值的字典没有意义-而是返回数组。

如果相同的服务可以返回书籍,CD或DVD,那么您可以返回带有键“ books”和数组值的字典。可能还有另一个密钥“ DVD”和一组DVD。例如,如果客户可以查询所有购买清单。

如果确定将响应仅解释为书籍列表(如果请求说“给我一个书籍列表”),则只需一个数组即可。


5

出于安全原因,第二种方法也是首选方法。较早的浏览器具有一个安全漏洞,如果该数据以JSON数组形式返回,则该漏洞使网页上的其他JavaScript代码可以窃取您的数据。因此,从历史上看,最佳实践是不返回JSON数组。实际上,有一些框架的“ json-ify”函数在传递数组时默认选择选项2。

https://stackoverflow.com/questions/3503102/what-are-top-level-json-arrays-and-why-are-they-a-security-risk

http://ejohn.org/blog/re-securing-json/


1

两者都是json并遵守REST。对于您的书籍更改清单,我将做出更具描述性的回应。或类似这样的东西:

{ "responceObject" : {

   results : 2,

    "Books": [
        {"author": "Dan Brown", "isbn": "123456", "title": "Digital Fortress"},
        {"author": "JK Rowling", "isbn": "234567", "title": "Harry Potter and the Chamber of Secrets"}
    ]

}}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.