JSON Patch and JSON Merge Patch

September 22, 2022

JSON Patch and 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,它基本上是由ADDREMOVEREPLACEMOVECOPY 一系列操作组成的。

下面一个简单的示例描述了一个 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检查。

KubernetesPATCH是支持JSON MERGER PATCHMERGE PATCH的,但是使用JSON MERGE PATCH的场景较少,也是建议使用JSON PATCH,最根本原因就是JSON MERGE PATCH的协议格式过于简单,难以应用在复杂场景。


LRF 记录学习、生活的点滴