记录json对比工具类


/**
 * @program: bedrock
 * @description: 复杂对象比较工具类
 * @author: 
 * @create: 2022-01-26 22:49
 **/

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description: 对象对比工具类
 * @author: guo-coffee
 */
public class ComparedUtils {

	/**
	 * 示例说明(更多事例可查看main方法):
	 * 对比json:{"id":"tom","username":"tom","age":18,"address":[{"province":"上海市"},{"city":"上海市"},{"disrtict":"静安区"},{"id":"静安区"}]}
	 *
	 * 示例一:调用compareJson(JSONObject json1, JSONObject json2, List<String> compareList)
	 *      假设指定username、address_province两列对比,compareList中需要放入username、address、address_province。
	 *      解释:若compareList集合中不放address,则表示整个address均不会进入比较,所以json嵌套多层时,将父key也需要放入compareList中
	 *
	 * 事例二:调用compareJson(JSONObject json1, JSONObject json2, List<String> filterList,boolean flag)
	 *      1、假设指定username、address_province两列不进行对比,filterList中需要放入username、address_province即可
	 *      2、假设整个address均不进行比对,filterList中需要放入username、address即可
	 */

	/**
	 * 默认过滤列名(由于项目会继承一些基类[例如ID、操作人、操作时间、修改人、修改时间等],基类中属性对比无任何意义,可以过滤掉)
	 */
	private static final List<String> DEFAULT_FILTER_COLUMNS = Arrays.asList("id","createDate","updateDate","createPersonId","createPersonName","updatePersonId","updatePersonName","concurrencyVersion","delflag","tendId");

	/**
	 * json嵌套多层时,父子key拼接字符
	 */
	private static final String SEPARATOR = "->";

	/**
	 * 两个对象对比(全部列对比)
	 * @param json1 对比对象,必传
	 * @param json2 对比对象,必传
	 * @return
	 */
	public static Map<String,List<String>> compareJson(JSONObject json1, JSONObject json2){
		return compareJson(json1,json2,false);
	}

	/**
	 * 两个对象对比
	 * @param json1 对比对象,必传
	 * @param json2 对比对象,必传
	 * @param flag 是否采用默认过滤策略-->true:采用 false:不采用
	 * @return
	 */
	public static Map<String,List<String>> compareJson(JSONObject json1, JSONObject json2, boolean flag){
		return compareJson(json1,json2,null,null,flag,null,null,new ArrayList<>(),new ArrayList<>());
	}

	/**
	 * 两个对象对比
	 * @param json1 对比对象,必传
	 * @param json2 对比对象,必传
	 * @param compareList 要比较的列
	 * @return
	 */
	public static Map<String,List<String>> compareJson(JSONObject json1, JSONObject json2, List<String> compareList){
		return compareJson(json1,json2,compareList,null,false,null,null,new ArrayList<>(),new ArrayList<>());
	}

	/**
	 * 两个对象对比
	 * @param json1 对比对象,必传
	 * @param json2 对比对象,必传
	 * @param filterList 不需要比较的列
	 * @param flag 是否需要过滤默认列-->true:需要 false:不需要
	 * @return
	 */
	public static Map<String,List<String>> compareJson(JSONObject json1, JSONObject json2, List<String> filterList,boolean flag){
		return compareJson(json1,json2,null,filterList,flag,null,null,new ArrayList<>(),new ArrayList<>());
	}

	/**
	 * 父类递归
	 * @param json1 对比对象
	 * @param json2 对比对象
	 * @param compareList 要比较的列
	 * @param filterList 不需要比较的列
	 * @param flag 是否需要过滤默认列-->true:需要 false:不需要
	 * @param key 当前比较的key,默认传null,主要用于递归时使用
	 * @param parentKey 拼接父类key,避免json嵌套多层时,返回key一致问题,默认传null,主要用于递归时使用
	 * @param equalsList 相同列,默认传new ArrayList<String>(),主要用于递归使用
	 * @param diffList 不同列,默认传传new ArrayList<String>(),主要用于递归使用
	 * @return
	 */
	private static Map<String,List<String>> compareJson(JSONObject json1, JSONObject json2,List<String> compareList,List<String> filterList,boolean flag, String key,String parentKey,List<String> equalsList,List<String> diffList) {
		Map<String,List<String>> map = new HashMap<>(2);
		Iterator i = json1.keySet().iterator();
		while (i.hasNext()) {
			// 当前比较的列
			key = (String) i.next();
			// 嵌套JSONArray时,当前key拼接父类key
			String str = StringUtils.isBlank(parentKey) ? key : parentKey + SEPARATOR + key;
			if (
				// 比较全部
					((compareList == null || compareList.isEmpty()) && (filterList == null || filterList.isEmpty()) && !flag)
							// 在【要比较的列】中
							|| (compareList != null && !compareList.isEmpty() && compareList.contains(str))
							// 不默认过滤 并且 不在【不需要比较的列】中
							|| (filterList != null && !filterList.isEmpty() && !filterList.contains(str) && !flag)
							// 过滤默认 并且 不在默认列 并且 不在【不需要比较的列】中
							|| (filterList != null && !filterList.isEmpty() && !filterList.contains(str) && flag && !DEFAULT_FILTER_COLUMNS.contains(key))
							// 只过滤默认
							|| ((filterList == null || filterList.isEmpty()) && flag && !DEFAULT_FILTER_COLUMNS.contains(key))
			) {
				/**
				 * 调用-->Object
				 */
				if (json1.get(key) != null && json2.get(key) != null){
					compareJson(json1.get(key), json2.get(key), compareList, filterList, flag, key, parentKey, equalsList, diffList);
				} else if (json1.get(key) == null && json2.get(key) == null) {
					equalsList.add(key);
				} else {
					diffList.add(key);
				}
			}
		}
		// 嵌套JSONArray时,只要有一列不一致,均为不一致
		equalsList.removeAll(diffList);
		// 嵌套JSONArray时,存在列明重复情况,集合去重处理
		map.put("equalsList",equalsList.stream().distinct().collect(Collectors.toList()));
		map.put("diffList",diffList.stream().distinct().collect(Collectors.toList()));
		return map;
	}

	/**
	 * Object
	 */
	private static void compareJson(Object json1, Object json2,List<String> compareList,List<String> filterList,boolean flag, String key,String parentKey,List<String> equalsList,List<String> diffList) {
		if (json1 instanceof JSONObject) {
			// 拼接父类key,避免json嵌套多层时,返回key一致问题
			parentKey = StringUtils.isBlank(parentKey)?key:parentKey+SEPARATOR+key;
			/**
			 * 调用-->父类递归
			 */
			compareJson((JSONObject) json1, (JSONObject) json2, compareList,filterList, flag, key ,parentKey,equalsList,diffList);
		} else if (json1 instanceof JSONArray) {
			/**
			 * 调用-->jsonArray
			 */
			compareJson((JSONArray) json1, (JSONArray) json2, compareList, filterList, flag, key ,parentKey,equalsList,diffList);
		} else if (json1 instanceof String) {
			try {
				String json1ToStr = json1.toString();
				String json2ToStr = json2.toString();
				/**
				 * 调用-->json字符串
				 */
				compareJson(json1ToStr, json2ToStr, key , parentKey,equalsList,diffList);
			} catch (Exception e) {
				System.out.println("转换发生异常 key:" + key);
				e.printStackTrace();
			}
		} else {
			/**
			 * 调用-->json字符串
			 */
			compareJson(json1.toString(), json2.toString(), key , parentKey,equalsList,diffList);
		}
	}

	/**
	 * json字符串
	 */
	private static void compareJson(String str1, String str2, String key,String parentKey,List<String> equalsList,List<String> diffList) {
		// 拼接父类key,避免json嵌套多层时,返回key一致问题
		parentKey = StringUtils.isBlank(parentKey)?key:parentKey+SEPARATOR+key;
		if (!str1.equals(str2)) {
			// 不一致的key
			diffList.add(parentKey);
		} else {
			// 一致
			equalsList.add(parentKey);
		}
	}

	/**
	 * jsonArray
	 */
	private static void compareJson(JSONArray json1, JSONArray json2,List<String> compareList,List<String> filterList,boolean flag, String key, String parentKey,List<String> equalsList,List<String> diffList) {
		// 拼接父类key,避免json嵌套多层时,返回key一致问题
		if (json1 != null && json2 != null && json1.size() == json2.size()) {
			Iterator i1 = json1.iterator();
			Iterator i2 = json2.iterator();
			while (i1.hasNext()) {
				/**
				 * 调用-->Object
				 */
				compareJson(i1.next(), i2.next(),compareList,filterList, flag, key , parentKey , equalsList,diffList);
			}
		} else {
			// JSONArray只要有一个为null则会不一致
			diffList.add(parentKey);
		}
	}

	/**
	 * 测试方法
	 * @param args
	 */
	public static void main(String[] args) {
		String st1 = "{\"id\":\"tom\",\"username\":\"tom\",\"age\":18,\"address\":[{\"province\":\"上海市\"},{\"city\":\"上海市\"},{\"disrtict\":\"静安区\"},{\"id\":\"静安区\"}],\"details\":{\"sex\":\"男\",\"mobile\":\"13811112222\"}}";
		String st2 = "{\"id\":\"tom\",\"username\":\"tom1\",\"age\":18,\"address\":[{\"province\":\"上海市1\"},{\"city\":\"上海市\"},{\"disrtict\":\"静安区1\"},{\"id\":\"静安区\"}],\"details\":{\"sex\":\"男\",\"mobile\":\"13811113333\"}}";

		JSONObject jsonObject1 = JSONObject.parseObject(st1);
		JSONObject jsonObject2 = JSONObject.parseObject(st2);

		System.out.println("全部对比:");
		Map<String,List<String>> map = compareJson(jsonObject1, jsonObject2);
		System.out.println("相同列==>"+map.get("equalsList"));
		System.out.println("不同列==>"+map.get("diffList"));

		System.out.println("默认过滤策略(id存在于默认策略,所以被过滤掉了):");
		Map<String,List<String>> map1 = compareJson(jsonObject1, jsonObject2,true);
		System.out.println("相同列==>"+map1.get("equalsList"));
		System.out.println("不同列==>"+map1.get("diffList"));

		System.out.println("指定列对比(只对比username、province):");
		// 注:要比较province,必须将address也放入集合中
		Map<String,List<String>> map2 = compareJson(jsonObject1, jsonObject2,Arrays.asList("username","address","address_province"));
		System.out.println("相同列==>"+map2.get("equalsList"));
		System.out.println("不同列==>"+map2.get("diffList"));

		System.out.println("指定列不对比(不对比username、province):");
		Map<String,List<String>> map3 = compareJson(jsonObject1, jsonObject2,Arrays.asList("username","address_province"),false);
		System.out.println("相同列==>"+map3.get("equalsList"));
		System.out.println("不同列==>"+map3.get("diffList"));

		System.out.println("指定列不对比+默认过滤策略(不对比username、province+默认过滤策略):");
		Map<String,List<String>> map4 = compareJson(jsonObject1, jsonObject2,Arrays.asList("username","address_province"),true);
		System.out.println("相同列==>"+map4.get("equalsList"));
		System.out.println("不同列==>"+map4.get("diffList"));

		System.out.println("指定列不对比+默认过滤策略(不对比username、address+默认过滤策略):");
		Map<String,List<String>> map5 = compareJson(jsonObject1, jsonObject2,Arrays.asList("username","address"),true);
		System.out.println("相同列==>"+map5.get("equalsList"));
		System.out.println("不同列==>"+map5.get("diffList"));
	}
}



GitHub 加速计划 / js / json
18
5
下载
适用于现代 C++ 的 JSON。
最近提交(Master分支:2 个月前 )
6be4e856 3 天前
663058e7 5 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐