创建 JSON 补丁文档
或者,除了其他答案中描述的方法之外,您还可以使用JSR 374中定义的Java API进行JSON处理(它不适用于Gson或Jackson)。需要以下依赖项:
<!-- Java API for JSON Processing (API) -->
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.1.2</version>
</dependency>
<!-- Java API for JSON Processing (implementation) -->
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>1.1.2</version>
</dependency>
然后,您可以从 JSON 文档创建 JSON 差异。它将生成 RFC 6902 中定义的 JSON 补丁文档:
JsonPatch diff = Json.createDiff(source, target);
应用于源文档时,JSON 修补程序将生成目标文档。JSON 补丁可以通过以下方式应用于源文档:
JsonObject patched = diff.apply(source);
创建 JSON 合并修补程序文档
根据您的需要,您可以创建 RFC 7396 中定义的 JSON 合并修补程序文档:
JsonMergePatch mergeDiff = Json.createMergeDiff(source, target);
应用于源文档时,JSON 合并修补程序将生成目标文档。要修补源,请使用:
JsonValue patched = mergeDiff.apply(source);
漂亮的打印 JSON 文档
要漂亮地打印 JSON 文档,您可以使用:
System.out.println(format(diff.toJsonArray()));
System.out.println(format(mergeDiff.toJsonValue()));
public static String format(JsonValue json) {
StringWriter stringWriter = new StringWriter();
prettyPrint(json, stringWriter);
return stringWriter.toString();
}
public static void prettyPrint(JsonValue json, Writer writer) {
Map<String, Object> config =
Collections.singletonMap(JsonGenerator.PRETTY_PRINTING, true);
JsonWriterFactory writerFactory = Json.createWriterFactory(config);
try (JsonWriter jsonWriter = writerFactory.createWriter(writer)) {
jsonWriter.write(json);
}
}
例
请考虑以下 JSON 文档:
{
"name": {
"first": "John",
"last": "Doe"
},
"address": null,
"birthday": "1980-01-01",
"company": "Acme",
"occupation": "Software engineer",
"phones": [
{
"number": "000000000",
"type": "home"
},
{
"number": "999999999",
"type": "mobile"
}
]
}
{
"name": {
"first": "Jane",
"last": "Doe",
"nickname": "Jenny"
},
"birthday": "1990-01-01",
"occupation": null,
"phones": [
{
"number": "111111111",
"type": "mobile"
}
],
"favorite": true,
"groups": [
"close-friends",
"gym"
]
}
以及以下代码来生成 JSON 补丁:
JsonValue source = Json.createReader(new StringReader(leftJson)).readValue();
JsonValue target = Json.createReader(new StringReader(rightJson)).readValue();
JsonPatch diff = Json.createDiff(source.asJsonObject(), target.asJsonObject());
System.out.println(format(diff.toJsonArray()));
它将生成以下输出:
[
{
"op": "replace",
"path": "/name/first",
"value": "Jane"
},
{
"op": "add",
"path": "/name/nickname",
"value": "Jenny"
},
{
"op": "remove",
"path": "/address"
},
{
"op": "replace",
"path": "/birthday",
"value": "1990-01-01"
},
{
"op": "remove",
"path": "/company"
},
{
"op": "replace",
"path": "/occupation",
"value": null
},
{
"op": "replace",
"path": "/phones/1/number",
"value": "111111111"
},
{
"op": "remove",
"path": "/phones/0"
},
{
"op": "add",
"path": "/favorite",
"value": true
},
{
"op": "add",
"path": "/groups",
"value": [
"close-friends",
"gym"
]
}
]
现在考虑以下代码来生成 JSON 合并修补程序:
JsonValue source = Json.createReader(new StringReader(leftJson)).readValue();
JsonValue target = Json.createReader(new StringReader(rightJson)).readValue();
JsonMergePatch mergeDiff = Json.createMergeDiff(source, target);
System.out.println(format(mergeDiff.toJsonValue()));
它将生成以下输出:
{
"name": {
"first": "Jane",
"nickname": "Jenny"
},
"address": null,
"birthday": "1990-01-01",
"company": null,
"occupation": null,
"phones": [
{
"number": "111111111",
"type": "mobile"
}
],
"favorite": true,
"groups": [
"close-friends",
"gym"
]
}
应用修补程序时的不同结果
应用修补程序文档时,上述方法的结果略有不同。请考虑以下将 JSON 修补程序应用于文档的代码:
JsonPatch diff = ...
JsonValue patched = diff.apply(source.asJsonObject());
System.out.println(format(patched));
它产生:
{
"name": {
"first": "Jane",
"last": "Doe",
"nickname": "Jenny"
},
"birthday": "1990-01-01",
"occupation": null,
"phones": [
{
"number": "111111111",
"type": "mobile"
}
],
"favorite": true,
"groups": [
"close-friends",
"gym"
]
}
现在考虑以下将 JSON 合并修补程序应用于文档的代码:
JsonMergePatch mergeDiff = ...
JsonValue patched = mergeDiff.apply(source);
System.out.println(format(patched));
它产生:
{
"name": {
"first": "Jane",
"last": "Doe",
"nickname": "Jenny"
},
"birthday": "1990-01-01",
"phones": [
{
"number": "111111111",
"type": "mobile"
}
],
"favorite": true,
"groups": [
"close-friends",
"gym"
]
}
在第一个示例中,该属性为 。在第二个示例中,它被省略了。这是由于JSON Merge Patch上的语义。来自 RFC 7396:occupation
null
null
如果目标确实包含该成员,则替换该值。合并修补程序中的空值被赋予特殊含义,以指示删除目标中的现有值。[...]
此设计意味着合并补丁文档适用于描述对 JSON 文档的修改,这些修改主要使用对象作为其结构,而不使用显式 null 值。合并修补程序格式并不适合所有 JSON 语法。