用于有限,无序集合的RESTful设计的Map或Array?

时间:2014-02-06 01:06:55

标签: json rest

我和一位同事就REST服务的设计进行了激烈的辩论。对于我们的大多数API,对集合的GET调用返回如下内容:

GET /resource
[
    { "id": 1, ... },
    { "id": 2, ... },
    { "id": 3, ... },
    ...
]

我们现在必须实现对一组属性的调用,这些属性的标识属性为" name" (不是" id"如上例所示)。此外,还有一组有限的属性,它们的发送顺序永远不会重要。我提出的规范看起来像这样:

GET /properties
[
    { "name": "{PROPERTY_NAME}", "value": "{PROPERTY_VALUE}", "description": "{PROPERTY_DESCRIPTION}" },
    { "name": "{PROPERTY_NAME}", "value": "{PROPERTY_VALUE}", "description": "{PROPERTY_DESCRIPTION}" },
    { "name": "{PROPERTY_NAME}", "value": "{PROPERTY_VALUE}", "description": "{PROPERTY_DESCRIPTION}" },
    ...
]

我的同事认为它应该是一张地图:

GET /properties
{
    "{PROPERTY_NAME}": { "value": "{PROPERTY_VALUE}", "description": "{PROPERTY_DESCRIPTION}" },
    "{PROPERTY_NAME}": { "value": "{PROPERTY_VALUE}", "description": "{PROPERTY_DESCRIPTION}" },
    "{PROPERTY_NAME}": { "value": "{PROPERTY_VALUE}", "description": "{PROPERTY_DESCRIPTION}" },
    ...
}

我引用与API其余部分的一致性作为以我的方式格式化响应集合的原因,同时他引用此特定集合是有限的并且顺序无关紧要。我的问题是,哪种设计最适合RESTful设计?为什么?

4 个答案:

答案 0 :(得分:4)

IIRC如何返回资源的属性与RESTful方法无关。

http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

从API客户端的角度来看,我更倾向于您的解决方案,因为它明确声明属性的名称是XYZ。

虽然您的同事解决方案意味着它是名称,但我如何确定(不阅读API文档)。尽量不要假设有关消费客户的任何事情,只因为你知道这意味着什么(并且可能很容易假设它意味着什么),对你的客户来说可能并不那么明显。

除此之外,如果您决定将该值从名称还原为ID,它可能会破坏消费客户端。在这种情况下,你已经在过去做过了。现在所有客户端都需要更改他们的代码,而他们不需要在您的解决方案中,除非他们需要新添加的ID(或其他一些属性)。

答案 1 :(得分:1)

对我而言,这种方法取决于您需要如何使用数据。消费系统预先知道属性名称,以便可以使用映射查找直接访问所需的记录而无需迭代每个项目吗?会不会有像...这样的方法。

GET /properties/{PROPERTY_NAME}

如果你需要按名称查找属性并且那种方法不可用,那么我会同意map方法,否则,我会使用数组方法在查询资源时提供一致的结果集合。

答案 2 :(得分:0)

我认为只要结果没有分页或排序服务器端,就可以返回地图。

如果您需要在服务器端对结果进行分页和排序,那么选择列表方法会更加安全,因为并非所有客户端都可以保留地图的顺序。

事实上,在JavaScript中没有内置保证地图将保持排序(另请参阅https://stackoverflow.com/a/5467142/817385)。

客户端需要实现一些逻辑来恢复排序顺序,当服务器和客户端使用不同的排序规则进行排序时,这可能会变得非常痛苦。 实施例

// server sent response sorted with german collation
var map = {
    'ä':{'first':'first'},
    'z':{'second':'second'}
}

// but we sort the keys with the default unicode collation algorigthm
Object.keys(map).sort().forEach(function(key){console.log(map[key])})

// Object {second: "second"}
// Object {first: "first"}

答案 3 :(得分:0)

晚了一点,但是对于那些在类似的斗争中偶然发现的人…… 我绝对同意一致性非常重要,并且通常会说数组是表示列表的最合适方法。同样,API应该设计为总体上有用,最好不要针对特定​​用例进行优化。当然,它可以使实施您今天面临的用例变得容易一些,但是当您明天实施另一种用例时,它可能会使您想自己动手做。话虽这么说,对于许多应用程序来说,地图形式的响应当然会更容易(可能更快)地使用。 考虑:

GET /properties
[
    { "name": "{PROPERTY_NAME}", "value": "{PROPERTY_VALUE}", "description": "{PROPERTY_DESCRIPTION}" },
    ...
]

GET /properties/*
{
    "{PROPERTY_NAME}": { "value": "{PROPERTY_VALUE}", "description": "{PROPERTY_DESCRIPTION}" },
    ...
}

所以/给您一个列表,而/ *给您一个地图。您可能会将/ *中的*用作标识符的通配符,因此实际上是在请求实体而不是集合。响应图中的键只是该通配符的扩展。 这样,您可以在整个API上保持一致性,而客户端在首选时仍可以享受地图格式的响应。同样,您可能可以在服务器端用很少的额外代码来实现这两个选项。