json diff就是找两个json的差异,找差异时维度可以是第一层字段维度。或者是深度差异比较。
为了演示这个功能,需要依赖两个工具包。
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.0-jre</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.1</version>
</dependency>
演示使用的两个样例JSON如下:
private String listN1 = "{\n" +
" \"employee\":\n" +
" {\n" +
" \"id\": \"1212\",\n" +
" \"fullName\": \"John Miles\",\n" +
" \"age\": 34,\n" +
" \"skills\": [\"C+++\", \"Java\", \"Python\"]\n" +
" }\n" +
"}";
private String listN2 = "{\n" +
" \"employee\":\n" +
" {\n" +
" \"id\": \"1212\",\n" +
" \"age\": 34,\n" +
" \"fullName\": \"John Miles\",\n" +
" \"skills\": [\"Java\", \"C++\", \"Python\"] \n" +
" } \n" +
"}";
第一层字段维度的json diff : 通过jackson json工具读入json字符串,并将其转换为HashMap
@Test
public void testJsonDiffOnField() throws Exception{
ObjectMapper mapper = new ObjectMapper();
TypeReference<HashMap<String, Object>> type =
new TypeReference<HashMap<String, Object>>() {};
HashMap<String, Object> j1 = mapper.readValue(listN1,type);
HashMap<String, Object> j2 = mapper.readValue(listN2,type);
MapDifference<String,Object> difference = Maps.difference(j1,j2);
}
深度比较:深度比较的思路是先将json平铺,随后再通过Maps.difference找出变化即可。因此这种方式需要用到一个平铺工具。
工具的核心思路就是递归的进行flat(平铺)操作,直到元素不再是集合类型。下面是flat(平铺)工具实现代码。
public class FlatMapUtil {
private FlatMapUtil() {
throw new AssertionError("No instances for you!");
}
public static Map<String, Object> flatten(Map<String, Object> map) {
return map.entrySet().stream()
.flatMap(FlatMapUtil::flatten)
.collect(LinkedHashMap::new, (m, e) -> m.put("/" + e.getKey(), e.getValue()), LinkedHashMap::putAll);
}
private static Stream<Map.Entry<String, Object>> flatten(Map.Entry<String, Object> entry) {
if (entry == null) {
return Stream.empty();
}
if (entry.getValue() instanceof Map<?, ?>) {
return ((Map<?, ?>) entry.getValue()).entrySet().stream()
.flatMap(e -> flatten(new AbstractMap.SimpleEntry<>(entry.getKey() + "/" + e.getKey(), e.getValue())));
}
if (entry.getValue() instanceof List<?>) {
List<?> list = (List<?>) entry.getValue();
return IntStream.range(0, list.size())
.mapToObj(i -> new AbstractMap.SimpleEntry<String, Object>(entry.getKey() + "/" + i, list.get(i)))
.flatMap(FlatMapUtil::flatten);
}
return Stream.of(entry);
}
}
最后再通过Maps.difference找出差异即可。
@Test
public void testJsonDiffByFlatten() throws Exception{
ObjectMapper mapper = new ObjectMapper();
TypeReference<HashMap<String, Object>> type =
new TypeReference<HashMap<String, Object>>() {};
HashMap<String, Object> j1 = mapper.readValue(listN1,type);
HashMap<String, Object> j2 = mapper.readValue(listN2,type);
Map<String, Object> flatten1 = FlatMapUtil.flatten(j1);
Map<String, Object> flatten2 = FlatMapUtil.flatten(j2);
MapDifference<String,Object> difference = Maps.difference(flatten1,flatten2);
}
比较
此外还可以通过第三方工具实现,比如下面的工具。具体使用可查看官方文档。
<!-- 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>
[1] 比较两个json,https://www.baeldung.com/jackson-compare-two-json-objects