部分更新RESTful服务中的复杂类型

时间:2011-01-12 01:28:25

标签: web-services json rest post put

我正在使用JSON和RESTful服务。实施就是这样。

GET on http://hostname/a返回

{
    "a": {
        "b": {
            "c1": "data1",
            "c2": "data2" 
        } 
    }
}

GET on http://hostname/a/b返回

{
    "b": {
        "c1": "data1",
        "c2": "data2" 
    } 
}

我想知道http://hostname/a

上POST(和PUT)的正确行为
{
    "a": {
        "b": {
            "c1": "newdata" 
        } 
    }
}

它应该只用值“newdata”更新c1,还是应该替换整个资源b,从而只包含c1(即c2被覆盖而不再存在)

3 个答案:

答案 0 :(得分:2)

在过去的几年中,我遇到了我在处理REST时遇到过的最争议的问题之一。

这是一个简单的答案:
普遍的共识是HTTP PUT方法已经替换了语义,因此c2被覆盖并且不再存在。
最近引入了PATCH方法来帮助人们处理部分更新。

现在,这个场景有两个复杂因素:
1)为什么PUT必须替换语义?进行部分更新有什么负面影响?我还没有听到一个非常有说服力的论点。

实际上,HTTP规范没有具体说PUT已经替换了语义,says

  

PUT方法请求   封闭的表示存储在   有效的请求URI

然而,它也说

  

HTTP / 1.1没有定义PUT的方式   方法影响原点的状态   服务器

2)如果您假设PUT已替换语义,则服务器可能会在未替换的表示中包含某些内容。例如如果表示包含链接,则执行不包含这些链接的表示的PUT不会“删除”这些链接。对于时间戳字段或上次修改的数据也是如此。永恒的问题是我们如何定义哪些内容在被客户端省略时被删除,哪些内容因为服务器这样说而停留!

就个人而言,我避免使用PUT,因为我发现“替换”语义太过限制。然而,最近我开始被Mike KellyMike Amundsen说服,可能PUT应该被认为比我们目前认可的更灵活。

答案 1 :(得分:1)

首先,如果您更改'b'资源,为什么不将POST(或PUT)发送到http://hostname/a/b而不仅仅是http://hostname/a?如果值得指出/链接的东西,它应该作为资源实现,根据RIA哲学,并且已经拥有它自己的URI。

答案 2 :(得分:0)

如果您将http://hostname/a的缓存副本发送到http://hostname/a/b?他们被允许多久不同步?

如果答案是"他们没有缓存" ...?

"分层系统的主要缺点是它们会增加数据处理的开销和延迟,从而降低用户感知的性能。对于支持缓存约束的基于网络的系统,这可以通过中间人的共享缓存的好处来抵消。" - 一篇着名的论文。