JSON Patch and JSON Merge Patch
JSON Patch vs JSON Merge Patch
PATCH
作为 HTTP
的一种 Method
, 近年来受到较多的关注,于是便提出关于使用 JSON
驱动 PATCH
格式的想法,这种格式用声明式的形式来描述两个JSON
文档之间的差异,IETF
发布了两种格式来解决这个问题: RFC 6902 (JSON Patch)和 RFC 7396 (JSON Merge Patch),两者各有优缺点,没有一种是可以适用于任何人的,让我们来看下他们的区别。
JSON PATCH
JSON PATCH
的格式类似于数据库事物,它是一个 JSON Document,
它基本上是由ADD
、REMOVE
、REPLACE
、MOVE
、COPY
一系列操作组成的。
下面一个简单的示例描述了一个 JSON
的内容:
{
"users" : [
{ "name" : "Alice" , "email" : "alice@example.org" },
{ "name" : "Bob" , "email" : "bob@example.org" }
]
}
在这个 JSON
中执行JSON PATCH
操作,更改Alice
的电子邮件,并且添加一个新的user
到数组中:
[
{
"op" : "replace" ,
"path" : "/users/0/email" ,
"value" : "alice@wonderland.org"
},
{
"op" : "add" ,
"path" : "/users/-" ,
"value" : {
"name" : "Christine",
"email" : "christine@example.org"
}
}
]
它的结果将是:
{
"users" : [
{ "name" : "Alice" , "email" : "alice@wonderland.org" },
{ "name" : "Bob" , "email" : "bob@example.org" },
{ "name" : "Christine" , "email" : "christine@example.org" }
]
}
一个JSON PATCH
有以下几个基本元素描述而成:
op
健表示操作类型。- 操作的参数由其他元素描述。
path
是指向作 为操作目标的JSON
中的指针,是一个必须存在的参数。
JSON PATCH
操作提供了一个 test
操作类型,它没有任何坏处,所以它不是一个数据操作运算符,它可以用来对执行过程进行断言,如果test
评估结果为false
,则可以中断执行。
JSON MERGE PATCH
JSON MERGE PATCH
它描述了 json document
的更改版本,与JSON PATCH
类似,区别在于它类似diff
文件,只包含执行后应该不同的document
节点。
如下是一个简单的JSON
文档,来说明JSON MERGE PATCH
的格式:
{
"a": "b",
"c": {
"d": "e",
"f": "g"
}
}
我们可以在上述的JSON
中运行如下的MERGE PATCH
:
{
"a":"z",
"c": {
"f": null
}
}
这个将 a
的值改为 z
,并且将删除 c
。
它看着很简单,但是这种简单性也带来了限制:
- 通过将
key
的值设置为null
来进行删除,这本质上就导致用户不能主动设置null
值。 - 数组不能被
PATCH
操作,如果想将一个元素添加到数组中,或者改变它的任何元素,那么必须要提供一个完整的数据才能执行。 MERGE PATCH
操作永远不会导致错误,任何格式错误的补丁都会被PATCH
,所以它是一种自由的格式,这不一定是好的,因为我们可能需要在执行完MEGER PATCH
之后进行JSON SCHEMA
的验证,错误就撤销PATCH
,但是目前实现不了。
总结
JOSN MERGE PATCH
是一种非常简单的格式,可用性有限,对于更复杂的用户,请使用JSON PATCH
,由于它使用与任何JSON
文档,该规范还提供了原子执行和执行前后执行test
检查。
Kubernetes
的 PATCH
是支持JSON MERGER PATCH
和 MERGE PATCH
的,但是使用JSON MERGE PATCH
的场景较少,也是建议使用JSON PATCH
,最根本原因就是JSON MERGE PATCH
的协议格式过于简单,难以应用在复杂场景。