我想知道如何在REST API(或类似API的REST)中处理对其他资源有影响的资源修改。
为了清楚起见,我将以账单为例。账单包含多行,每行包含金额。该法案还有一个财产说明总金额,这是所有行的总和。量。
使用JSON的账单表示可以是:
{
id: 156,
amount: 12,
lines: [
1: {
label : 'Item 1'
amount: 8
}
2: {
label: 'Item 2',
amount: 4
}
]
}
更新生产线的最佳方法是什么,并告知帐单金额已更改?
我提出了一些想法,它们都有优点和缺点。
解决方案1:使用一种资源
该解决方案来自这个问题:"资源是否应该影响其他资源?" 回答没有导致只有一个资源用于账单及其行。这允许在账单资源上使用补丁。 此外,我们可以争辩说没有线条的账单毫无意义。
请求
PATCH api.something.com/bills/156
{
lines: [
1: {
amount: 4
}
]
}
或者,使用RFC6902
PATCH api.something.com/bills/156
[
{ "op": "replace", "path": "/lines/1/amount", "value": 4 }
]
响应
HTTP/1.1 200 Success
{
id: 156,
amount: 8,
lines: [
1: {
label : 'Item 1'
amount: 4
}
2: {
label: 'Item 2',
amount: 4
}
]
}
优点:
缺点:
解决方案2:调用子资源并重定向
如果我们同意对线路使用子资源,则一个解决方案是使用303重定向响应,Roy T. Fielding proposes。
线路添加
请求
POST api.something.com/bills/156/lines
{
label: 'Item 156',
amount: 10
}
响应
HTTP/1.1 303 See other
Location: https://api.something.com/bills/156
行更新
请求
PATCH api.something.com/bills/156/lines/
{
amount: 5
}
响应
HTTP/1.1 303 See other
Location: https://api.something.com/bills/156
行删除
请求
DELETE api.something.com/bills/156/lines/2
响应
HTTP/1.1 303 See other
Location: https://api.something.com/bills/156
缺点:
优点:
解决方案3:使用链接
第三种选择是使用链接,例如使用HAL。 HAL允许添加链接属性。引入hasChange属性可以解决问题。
行数额更新将如下所示:
请求
PATCH api.something.com/bills/156/lines/1
{
amount: 5
}
响应
HTTP/1.1 200 Success
{
amount:5,
label: "Item 1",
"_links": {
"bill": {
"href": "/bill/156",
hasChanged: true
}
}
}
优点:
缺点:
我很想知道是否有人可以建议赞成或反对其中一种解决方案,因为它们对我来说都很有趣。