阅读量:4
网上找到的比较JSON工具类,比较两个JSON对象之间的差异,并将差异字段按照原JSON对象的树状结构展现出来,方便对数据进行对比。对原有方法进行了部分优化。
package com.summer.toolkit.util; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import java.util.*; /** * @author author */ @Slf4j public class CompareJsonUtils { /** * 正则表达式,匹配数组下标,如:[0]、[1] */ public static final String PATTERN = "\\[[0-9]+\\]"; /** * 分隔符 */ public static final String REGEX = "\\."; /** * 连接符 */ public static final String CONNECTOR = "."; /** * 旧的数据Key值 */ public static final String OLD_VALUE_KEY = "oldValue"; /** * 新的数据Key值 */ public static final String NEW_VALUE_KEY = "newValue"; /** * 将两个JSON对象进行比较 * * @param oldJsonStr 旧的JSON字符串 * @param newJsonStr 新的JSON字符串 * @return 比较结果转换为JSON字符串 */ public static String compareJsonObject(String oldJsonStr, String newJsonStr) { // 默认不排除字段 List<String> excludes = new ArrayList<>(); return CompareJsonUtils.compareJsonObject(oldJsonStr, newJsonStr, excludes); } /** * 比较两个JSON对象,排除指定字段后的差异 * * @param oldJsonStr 旧的JSON字符串 * @param newJsonStr 新的JSON字符串 * @param excludes 需要排除比较的字段列表 * @return 返回排除指定字段后的差异JSON对象 */ public static String compareJsonObject(String oldJsonStr, String newJsonStr, List<String> excludes) { // 将字符串转换为json对象 JSON oldJson = JSON.parseObject(oldJsonStr); JSON newJson = JSON.parseObject(newJsonStr); // 递归遍历json对象所有的key-value,将其封装成path:value格式进行比较 Map<String, Object> oldMap = new LinkedHashMap<>(32); Map<String, Object> newMap = new LinkedHashMap<>(32); CompareJsonUtils.convertJsonToMap(oldJson, "", oldMap); CompareJsonUtils.convertJsonToMap(newJson, "", newMap); // 去掉不需要对比的字段 CompareJsonUtils.excludeFields(oldMap, excludes); CompareJsonUtils.excludeFields(newMap, excludes); // 比较两个map,返回不同数据 Map<String, Object> temp = new LinkedHashMap<>(oldMap); Map<String, Object> differenceMap = CompareJsonUtils.compareMap(temp, newMap); // 将最终的比较结果把不相同的转换为json对象返回 JSONObject result = CompareJsonUtils.convertMapToJson(differenceMap); log.info("对比JSON结果为:{}", result); return JSON.toJSONString(result); } /** * 从给定的Map中排除指定的字段 * * @param map 包含字段的Map * @param excludes 要排除的字段列表 */ public static void excludeFields(Map<String, Object> map, List<String> excludes) { if (Objects.nonNull(map) && CollectionUtils.isNotEmpty(excludes)) { Iterator<Map.Entry<String, Object>> iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, Object> entry = iterator.next(); if (Objects.nonNull(entry)) { if (excludes.contains(entry.getKey())) { iterator.remove(); } } } } } /** * 将json数据转换为map存储用于比较 * * @param json JSON对象 * @param root 根对象名称 * @param resultMap 结果 */ private static void convertJsonToMap(Object json, String root, Map<String, Object> resultMap) { if (json instanceof JSONObject) { JSONObject jsonObject = ((JSONObject) json); for (String key : jsonObject.keySet()) { Object value = jsonObject.get(key); String newRoot = "".equals(root) ? key + "" : root + CompareJsonUtils.CONNECTOR + key; if (value instanceof JSONObject || value instanceof JSONArray) { CompareJsonUtils.convertJsonToMap(value, newRoot, resultMap); } else { resultMap.put(newRoot, value); } } } else if (json instanceof JSONArray) { JSONArray jsonArray = (JSONArray) json; for (int i = 0; i < jsonArray.size(); i++) { Object value = jsonArray.get(i); String newRoot = "".equals(root) ? "[" + i + "]" : root + ".[" + i + "]"; if (value instanceof JSONObject || value instanceof JSONArray) { CompareJsonUtils.convertJsonToMap(value, newRoot, resultMap); } else { resultMap.put(newRoot, value); } } } } /** * 比较两个map,返回不同数据 * * @param oldMap 旧数据MAP对象 * @param newMap 新数据MAP对象 * @return 返回值,两者的差异 */ private static Map<String, Object> compareMap(Map<String, Object> oldMap, Map<String, Object> newMap) { // 遍历newMap,将newMap的不同数据装进oldMap,同时删除oldMap中与newMap相同的数据 CompareJsonUtils.compareNewToOld(oldMap, newMap); // 将旧的有新的没有的数据封装数据结构存在旧的里面 CompareJsonUtils.compareOldToNew(oldMap); return oldMap; } /** * 将旧的有新的没有的数据封装数据结构存在旧的里面 * * @param oldMap 旧数据结构 */ private static void compareOldToNew(Map<String, Object> oldMap) { // 统一oldMap中newMap不存在的数据的数据结构,便于解析 for (Map.Entry<String, Object> item : oldMap.entrySet()) { String key = item.getKey(); Object value = item.getValue(); if (!(value instanceof Map)) { // 此处并没有添加数据,而是将key值对应的value值进行修改,所以并没有改变map的数量 Map<String, Object> differenceMap = CompareJsonUtils.buildDifferenceMap(value, ""); oldMap.put(key, differenceMap); } } } /** * 将新的map与旧的比较,并将数据统一存在旧的里面 * * @param oldMap 旧数据 * @param newMap 新数据 */ private static void compareNewToOld(Map<String, Object> oldMap, Map<String, Object> newMap) { for (Map.Entry<String, Object> item : newMap.entrySet()) { String key = item.getKey(); Object newValue = item.getValue(); if (oldMap.containsKey(key)) { Object oldValue = oldMap.get(key); if (newValue.equals(oldValue)) { oldMap.remove(key); } else { Map<String, Object> differenceMap = CompareJsonUtils.buildDifferenceMap(oldValue, newValue); oldMap.put(key, differenceMap); } } else { Map<String, Object> differenceMap = CompareJsonUtils.buildDifferenceMap("", newValue); oldMap.put(key, differenceMap); } } } /** * 将已经找出不同数据的map根据key的层级结构封装成json返回 * * @param map 入参 * @return 返回值 */ private static JSONObject convertMapToJson(Map<String, Object> map) { JSONObject resultJsonObject = new JSONObject(); for (Map.Entry<String, Object> item : map.entrySet()) { String key = item.getKey(); Object value = item.getValue(); String[] paths = key.split(CompareJsonUtils.REGEX); int i = 0; // 用于深度标识对象 Object remarkObject = null; int indexAll = paths.length - 1; while (i <= paths.length - 1) { String path = paths[i]; if (i == 0) { // 初始化对象标识 if (resultJsonObject.containsKey(path)) { remarkObject = resultJsonObject.get(path); } else { if (indexAll > i) { if (paths[i + 1].matches(CompareJsonUtils.PATTERN)) { remarkObject = new JSONArray(); } else { remarkObject = new JSONObject(); } resultJsonObject.put(path, remarkObject); } else { resultJsonObject.put(path, value); } } i++; continue; } // 匹配集合对象 if (path.matches(CompareJsonUtils.PATTERN)) { int startIndex = path.lastIndexOf("["); int endIndext = path.lastIndexOf("]"); int index = Integer.parseInt(path.substring(startIndex + 1, endIndext)); if (indexAll > i) { if (paths[i + 1].matches(CompareJsonUtils.PATTERN)) { while (((JSONArray) remarkObject).size() <= index) { if (((JSONArray) remarkObject).size() == index) { ((JSONArray) remarkObject).add(index, new JSONArray()); } else { //((JSONArray) remarkObject).add(null); ((JSONArray) remarkObject).add(new JSONObject()); } } } else { while (((JSONArray) remarkObject).size() <= index) { if (((JSONArray) remarkObject).size() == index) { ((JSONArray) remarkObject).add(index, new JSONObject()); } else { //((JSONArray) remarkObject).add(null); ((JSONArray) remarkObject).add(new JSONObject()); } } } remarkObject = ((JSONArray) remarkObject).get(index); } else { while (Objects.nonNull(remarkObject) && ((JSONArray) remarkObject).size() <= index) { if (((JSONArray) remarkObject).size() == index) { ((JSONArray) remarkObject).add(index, value); } else { //((JSONArray) remarkObject).add(null); ((JSONArray) remarkObject).add(new JSONObject()); } } } } else { if (indexAll > i) { if (paths[i + 1].matches(CompareJsonUtils.PATTERN)) { if (!((JSONObject) remarkObject).containsKey(path)) { ((JSONObject) remarkObject).put(path, new JSONArray()); } } else { if (!((JSONObject) remarkObject).containsKey(path)) { ((JSONObject) remarkObject).put(path, new JSONObject()); } } remarkObject = ((JSONObject) remarkObject).get(path); } else if (Objects.nonNull(remarkObject)) { ((JSONObject) remarkObject).put(path, value); } } i++; } } return resultJsonObject; } /** * 构建差异Map,用于比较旧值和新值之间的差异 * * @param oldValue 旧值 * @param newValue 新值 * @return differenceMap 差异Map,包含'oldValue'和'newValue'两个键值对 */ public static Map<String, Object> buildDifferenceMap(Object oldValue, Object newValue) { Map<String, Object> differenceMap = new HashMap<>(4); differenceMap.put(CompareJsonUtils.OLD_VALUE_KEY, oldValue); differenceMap.put(CompareJsonUtils.NEW_VALUE_KEY, newValue); return differenceMap; } /** * 比较两个JSON对象并返回它们之间的差异 */ public static void main(String[] args) { String oldStr = "{a:'aaa',b:'bbb',c:'aaa',d:'bbb'}"; String newStr = "{a:'aa',b:'bb',e:'bb'}"; System.out.println(CompareJsonUtils.compareJsonObject(oldStr, newStr)); } }
以上测试方法结果为:
{ "b": { "newValue": "bb", "oldValue": "bbb" }, "c": { "newValue": "", "oldValue": "aaa" }, "d": { "newValue": "", "oldValue": "bbb" }, "e": { "newValue": "bb", "oldValue": "" } }