如何使用Jackson为两个对象创建JSON合并补丁文档



我们有一个应用程序,在Jackson中为JSON处理进行了大量投资。具体来说,RESTAPI中使用了许多带注释的模型对象。现在我们需要调用一个REST API,其中PATCH需要一个合并补丁JSON文档。考虑到原始对象和更改后的对象,用JSON-P创建这一点很简单,但我还没有找到用Jackson创建的方法。

这个代码工作并完成任务:

public <T> String createMergePatch(T source, T target) throws IOException {
var sourceBytes = objectMapper.writeValueAsBytes(source);
var targetBytes = objectMapper.writeValueAsBytes(target);
// Changing framework - not at all ideal
var sourceJson = Json.createReader(new ByteArrayInputStream(sourceBytes)).readValue();
var targetJson = Json.createReader(new ByteArrayInputStream(targetBytes)).readValue();
var mergePatch = Json.createMergeDiff(sourceJson, targetJson);
return mergePatch.toJsonValue().toString();
}

当源对象和目标对象转换为JSON时,将使用Jackson注释。然后,我们切换框架以获得createMergeDiff可以处理的东西。这是低效的,我们需要包含我们不想要的依赖项,但输出是正确的。

最后,我的问题是,是否有一种更好的方法可以用Jackson实现这一点,而不必引入另一个JSON框架,也不必在JSON和对象之间往返?

下面是一个我认为您要求的示例。

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import java.io.IOException;
public class Main {
public static void main(String[] args) throws IOException {

String json1 = "{"name":"John","age":30,"city":"New York"}";
String json2 = "{"name":"John","age":30,"city":"New York","country":"USA"}";
String result = createMergePatchWith(json1, json2);
System.out.println(result);
}
public static String createMergePatchWith(String json1, String json2) throws IOException {
ObjectMapper mapper = new ObjectMapper();
JsonNode jsonNode1 = mapper.readTree(json1);
JsonNode jsonNode2 = mapper.readTree(json2);
JsonNode mergePatch = doMergeWithJackson(jsonNode1, jsonNode2);
return mapper.writeValueAsString(mergePatch);
}
private static JsonNode doMergeWithJackson(JsonNode jsonNode1, JsonNode jsonNode2) {
if (jsonNode1.isObject() && jsonNode2.isObject()) {
ObjectNode objectNode = (ObjectNode) jsonNode1;
jsonNode2.fields().forEachRemaining(entry -> {
JsonNode value = entry.getValue();
if (value.isObject()) {
objectNode.set(entry.getKey(), doMergeWithJackson(objectNode.get(entry.getKey()), value));
} else {
objectNode.set(entry.getKey(), value);
}
});
return objectNode;
}
return jsonNode2;
}

}

输出:{"名字":"约翰","年龄":30,"城市":"纽约","国家":"美国"}

最新更新