具有List属性的REST资源

时间:2010-06-27 22:49:53

标签: json rest

我想对我目前的架构提供一些反馈。

我有一个“人”资源可通过GET和PUT请求提供给:/ users / people / {key}。该资源以JSON格式生成并接受“Person”对象。

这是GET /users/people/{key}可能返回的JSON示例:

{
 "age":29,
 "firstName":"Chiquita",
 "phoneNumbers":[
   {"key":"49fnfnsa0sas","number":"555-555-5555","deleted":false}
   {"key":"838943bdfb-f","number":"777-777-7777","deleted":false}
  ]
}

正如您所看到的,“Person”有一些典型的字段,例如“firstName”和“age”以及一个棘手的集合类型字段:“phoneNumbers”。

我正在尝试设计资源,以便在更新资源时,客户端只需要发回需要更新的字段。例如,仅更新此人的firstName:

PUT users/people/{key}

{
 "firstName":"New first name",
}

通过这种方式,来回传输的不必要信息少得多(根据资源的大小减少的程度)

我的问题是,我该如何处理列表属性,例如“phoneNumbers”。我应该编写一些更复杂的代码来检查旧列表中的现有PhoneNumber密钥,如果没有引用它们就不会触摸它们,如果有匹配的密钥则更新它们,如果有一个带有新密钥的PhoneNumber则添加它们?或者我应该编写一些更简单的代码,将每个“phoneNumbers”列表属性视为另一个完全覆盖的字段,如果它包含在“PUT”请求体中?是否有一种标准的接受方法,其中一种策略被证明比另一种策略更少问题?或者我是否可以自行决定?

谢谢!

3 个答案:

答案 0 :(得分:2)

PUT的定义是它必须具有替换语义。引入PATCH动词以允许进行部分更新。见http://tools.ietf.org/html/rfc5789

至于如何进行diff格式,确实没有正确或错误的方法。这实际上取决于你的背景。

答案 1 :(得分:1)

我认为让每次更改内容时客户端上传当前人的所有信息都是最有意义的。但是,如果出现这种情况可能还不够:

  • 在典型情况下,每次更改都必须来回发送大量数据。
  • 多人可以同时编辑同一个人。

如果您的人物对象很大,您可以考虑采用差异/补丁方法。在发送新版本之前,请将其与旧版本进行比较。如果单个字段(例如firstName)发生更改,只需将其列在JSON对象中:

{
 "firstName":"New first name"
}

对于电话号码阵列,列出要按键删除的电话号码,并列出要像平常一样添加的新电话号码。像这样:

{
 "+phoneNumbers":[
  {"key":"123456789abc","number":"555-123-4567"}
 ],
 "-phoneNumbers":[
  "49fnfnsa0sas"
 ]
}

您也可以在Google上搜索“json diff”,看看您发现的任何结果是否有用。

正如我之前所说,除非你有充分的理由去实现这种复杂性,否则最好让客户重新上传整个人物对象来更新它。

答案 2 :(得分:1)

正如其他人所说,PUT需要更换整个资源。但是,作为架构师,您可以设计资源。也许人事记录中包含电话号码。或者更像是在单独的表中使用电话号码设置关系数据库的方式。在这种情况下,GET / users / people / {key}只会获得名称和年龄,如果您想要一种获取电话号码和名称的方法,您可以定义查询参数。 GET / users / userphone / {key}将获得包含该人的电话号码的资源,即阵列。

回到将Person资源定义为包含其中的电话号码,使用POST没有任何问题。例如,POST的经典用法是将评论发布到网页或删除评论。没有理由不能定义POST操作来添加或删除电话号码。无论好坏,POST都是随时随地的方法。

(我注意到这里的按钮是“发布你的答案”,而不是“提出你的答案”,并且有充分的理由。)