最近看了一下fabric8的源码,发现对于k8s资源的更新都是采用了JSONPatch的方式,看是市面上却没有关于JSONPatch一键使用的工具类,所以自己搜了一下GitHub上开源的项目和自己的研究,写了一个方便易用的工具类,以方便大家的ctrl+C, ctrl+V。
用的依赖为zjsonpath,其中封装了有关JSONDiff的方法;
<!-- json Patch -->
<dependency>
<groupId>com.flipkart.zjsonpatch</groupId>
<artifactId>zjsonpatch</artifactId>
<version>0.4.12</version>
</dependency>
@Data
public class JSONPatch {
/*
* RFC6902 - 4.
*/
private String op;
private String path;
private Object value;
}
package com.victor.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.flipkart.zjsonpatch.JsonDiff;
import com.flipkart.zjsonpatch.JsonPatch;
import com.victor.model.JSONPatch;
import java.util.List;
/**
* JSONPatch工具类,主要为两个功能:
* 1.通过源对象和目标对象获得JSONPatch, JSONPath可以是数组或字符串;
* 2.根据源对象, 通过JSONPatch字符串或数组获得目标对象;
*
*/
public class JSONPatchUtil {
private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* 将两个对象之间的差别以JSONPatch的形式呈现
*
* @param source 老对象
* @param target 新对象
* @return List<JSONPatch>
*/
public static List<JSONPatch> getJSONPatch(Object source, Object target) {
try {
JsonNode oldJson = MAPPER.valueToTree(source);
JsonNode newJson = MAPPER.valueToTree(target);
JsonNode jsonNode = JsonDiff.asJson(oldJson, newJson);
String jsonPatchStr = MAPPER.writeValueAsString(jsonNode);
return MAPPER.readValue(jsonPatchStr, new TypeReference<>() {
});
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
/**
* 将两个对象之间的差别以JSONPatch字符串的形式呈现
*
* @param source 老对象
* @param target 新对象
* @return List<JSONPatch>的json形式
*/
public static String getJSONPatchStr(Object source, Object target) {
try {
JsonNode oldJson = MAPPER.valueToTree(source);
JsonNode newJson = MAPPER.valueToTree(target);
JsonNode jsonNode = JsonDiff.asJson(oldJson, newJson);
return MAPPER.writeValueAsString(jsonNode);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
/**
* 应用JSONPatch生成目标对象
*
* @param patch JSONPatch字符串表达形式
* @param source 原对象
* @param <T> 源对象和目标对象的类型
* @return 目标对象
*/
public static <T> T applyJSONPatch(String patch, T source) {
try {
JsonNode oldJson = MAPPER.valueToTree(source);
JsonNode patchJson = MAPPER.readTree(patch);
JsonNode newJson = JsonPatch.apply(patchJson, oldJson);
String targetStr = MAPPER.writeValueAsString(newJson);
return MAPPER.readValue(targetStr, new TypeReference<>() {
});
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
/**
* 应用JSONPatch生成目标对象
*
* @param patch JSONPatch数组表达形式
* @param source 原对象
* @param <T> 源对象和目标对象的类型
* @return 目标对象
*/
public static <T> T applyJSONPatch(List<JSONPatch> patch, T source) {
try {
return applyJSONPatch(MAPPER.writeValueAsString(patch), source);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
package com.victor.json;
import cn.hutool.setting.yaml.YamlUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.flipkart.zjsonpatch.JsonDiff;
import com.victor.model.JSONPatch;
import com.victor.util.JSONPatchUtil;
import org.testng.annotations.Test;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* @description:
*/
@SuppressWarnings("rawtypes")
public class JSONPatchTest {
private final ObjectMapper objectMapper = SingletonHolder.patchMapper;
private final Map oldObj = YamlUtil.loadByPath("test1.yaml", Map.class);
private final Map newObj = YamlUtil.loadByPath("test2.yaml", Map.class);
@Test
public void testJSONPatchStr() {
String s = JSONPatchUtil.getJSONPatchStr(oldObj, newObj);
System.out.println(s);
}
@Test
public void testJSONPatch() {
List<JSONPatch> jsonPatch = JSONPatchUtil.getJSONPatch(oldObj, newObj);
System.out.println(jsonPatch);
}
@Test
public void applyJSONPatchStr() {
String patch = JSONPatchUtil.getJSONPatchStr(oldObj, newObj);
Map map = JSONPatchUtil.applyJSONPatch(patch, oldObj);
System.out.println(newObj.equals(map));
}
@Test
public void applyJSONPatch() {
List<JSONPatch> patch = JSONPatchUtil.getJSONPatch(oldObj, newObj);
Map map = JSONPatchUtil.applyJSONPatch(patch, oldObj);
System.out.println(newObj.equals(map));
}
}