JSON Patch

JSON Path是在使用Kubernetes API的过程中首次使用的. 使用API做扩缩容的时候, 发送整个Deployment的全文不是个明智的做法, 虽然可行. 因此便使用了JSON Patch.

1
2
3
4
5
6
7
JsonObject item = new JsonObject();
item.add("op", new JsonPrimitive("replace"));
item.add("path", new JsonPrimitive("/spec/replicas"));
item.add("value", new JsonPrimitive(instances));
JsonArray body = new JsonArray();
body.add(item);
appsV1beta1Api.patchNamespacedScaleScale(id, namespace, body, null);

fabric8s提供的kubernetes-client中使用的zjsonpatch则封装了JSON Patch操作. 例如在做扩缩容的时候或者当前的deployment, 修改replicas的值. 然后比较对象的不同(JsonDiff.asJson(sourceJsonNode, targetJsonNode)).

下面的内容部分翻译自JSON PATH, 有兴趣的可以跳转看原文.

什么是JSON Patch

JSON Path是一直描述JSON文档变化的格式. 使用它可以避免在只需要修改某一部分的时候发送整个文档内容. 当与HTTP PATCH方法混合使用的时候, 它允许在标准规范的基础上使用HTTP APIs进行部分更新.

补丁(Patch)内容的格式也是JSON.

JSON Patch由IETF在RFC 6902中规范.

简单的例子

原始文档

1
2
3
  "baz": "qux",
  "foo": "bar"
}

补丁

1
2
3
4
5
[
  { "op": "replace", "path": "/baz", "value": "boo" },
  { "op": "add", "path": "/hello", "value": ["world"] },
  { "op": "remove", "path": "/foo"}
]

结果

1
2
3
4
{
  "baz": "boo",
  "hello": ["world"]
}

如何实现

一个JSON Path文档是一个包含了一组patch操作的JSON文件. 支持的patch操作包括”add”, “remove”, “replace”, “move”, “copy”和”test”. 这些patch操作是按照顺序应用的: 如果有任何一个操作失败, 整个patch都会被终止.

JSON Pointer(指针)

JSON指针IETF RFC 6901定义了一个如何在JSON文档中定位指定值的字符格式. 用来在所有的JSON Patch操作中指定要修改的文档部分.

JSON指针是使用/分隔的token字符串, 这些token指定了对象的key或者是数组的索引. 例如, 给定JSON

1
2
3
4
5
6
{
  "biscuits": [
    { "name": "Digestive" },
    { "name": "Choco Leibniz" }
  ]
}

/biscuits将指向数组biscuits, 同时/biscuits/1/name指向Choco Leibniz.

要指向JSON文档的根要使用一个空的字符串''. 指针/并不是指向根, 而是指向根上key为""的位置(在JSON中是非法的).

操作

Add

1
{ "op": "add", "path": "/biscuits/1", "value": { "name": "Ginger Nut" } }

在对象上增加一个值, 或者数组中插入数据. 如果是数组, 值将被插入到给定位置的前面. -用来表示插入到数组的尾部.

Remove

1
{ "op": "remove", "path": "/biscuits" }

删除对象或者数组中的值.

Replace

1
{ "op": "replace", "path": "/biscuits/0/name", "value": "Chocolate Digestive" }

替换一个值. 等同于先删除再增加.

Copy

1
{ "op": "copy", "from": "/biscuits/0", "path": "/best_biscuit" }

从一个位置(from)复制数据到指定的位置(path)上. fromto都是JSON指针.

Move

1
{ "op": "move", "from": "/biscuits", "path": "/cookies" }

从一个位置(from)移动数据到指定的位置(path)上. fromto都是JSON指针.

Test

1
{ "op": "test", "path": "/best_biscuit/name", "value": "Choco Leibniz" }

检查某个位置的值是否是指定的值.如果失败, 整个Patch操作就会终止.

JavaScript

Python

PHP

Ruby

Perl

C

Java

Scala

C++

C

Go

Haskell

Erlang

Elm

测试套件

github上维护的一组一致性测试 github.com/json-patch/json-patch-tests

Comments

comments powered by Disqus