zoukankan      html  css  js  c++  java
  • JAVA 实现json diff

    使用java实现复杂结构多层级的json diff

    主要思路:遍历json,根据key排序,判断json element类型,如果是jsonArray的话,转成list并排序,并循环验证list中的每个json element是否相等

    package service.utils;
    
    import com.google.gson.*;
    import org.slf4j.*;
    import org.testng.Assert;
    
    import java.util.*;
    
    
    public class JsonDiffUtil {
    
        private static final JsonParser parser = new JsonParser();
        private static final Gson gson = new Gson();
    
        //默认是忽略值比较
        private boolean diffValue = false;
    
        private static final Logger logger = LoggerFactory.getLogger(JsonDiffUtil.class);
    
        public JsonDiffUtil(){};
    
        public JsonDiffUtil(boolean diffValue){
            this.diffValue = diffValue;
        }
    
    
        /*
         * 验证两个json字符串结构是否一致,正反两次比较
         */
        public void diff(String exceptJson,String actualJson){
            Assert.assertTrue(equals(exceptJson, actualJson));
            Assert.assertTrue(equals(actualJson, exceptJson));
        }
    
        /**
         * 比较两个json字符串是否
         */
        public boolean equals(String exceptJson, String actualJson) {
            if(exceptJson.equals(actualJson)){
                return true;
            }
            //json String 转 JsonElement
            JsonElement exceptJsonElement = parser.parse(exceptJson);
            JsonElement actualJsonElement = parser.parse(actualJson);
    
            //按key排序
            sort(exceptJsonElement);
            sort(actualJsonElement);
    
            return equals(exceptJsonElement, actualJsonElement);
        }
    
        private boolean equals(JsonElement except, JsonElement actual) {
            if (except.isJsonObject()) {
                return equals(except.getAsJsonObject(), actual.getAsJsonObject());
            } else if (except.isJsonArray() ) {
                return equals(except.getAsJsonArray(), actual.getAsJsonArray());
            } else if (except.isJsonPrimitive()) {
                return equals(except.getAsJsonPrimitive(), actual.getAsJsonPrimitive());
            }  else {
                logger.info("except= {},actual= {}",except,actual);
                return false;
            }
        }
    
        private boolean equals(JsonObject except, JsonObject actual) {
            Set<String> exceptSet = except.keySet();
            for (String key : exceptSet) {
                JsonElement exceptValue = except.get(key);
                JsonElement actualValue = actual.get(key);
                if(actualValue == null){
                    logger.error("not found key:"+key);
                    return false;
                }
                if (exceptValue.isJsonArray() && exceptValue.getAsJsonArray().size() != actualValue.getAsJsonArray().size()) {
                    logger.error("JSON Array size not equal,key is {}",key);
                    return false;
                }
                boolean flag = equals(exceptValue, actualValue);
                if(!flag){
                    if(exceptValue.isJsonPrimitive()){
                        if (diffValue) {
                            logger.error("value not equal,key is {}, except value is {}, actual value is {}",key,exceptValue,actualValue);
                        }
                        else {
                            logger.error("not found key:"+key);
                        }
    
                    }
                    return false;
                }
    
    
            }
            return true;
        }
    
        private boolean equals(JsonArray exceptArray, JsonArray actualArray) {
            List<JsonElement> exceptList = toSortedList(exceptArray);
            List<JsonElement> actaulList = toSortedList(actualArray);
            for (int i = 0; i < exceptList.size(); i++) {
                if (!equals(exceptList.get(i), actaulList.get(i))) {
                    return false;
                }
            }
            return true;
        }
    
        private boolean equals(JsonPrimitive except, JsonPrimitive actual) {
    
            if(!diffValue){
                return actual != null;
            }
            return except.equals(actual);
        }
    
        private List<JsonElement> toSortedList(JsonArray array) {
            List<JsonElement> list = new ArrayList<>();
            array.forEach(list::add);
            list.sort(Comparator.comparing(gson::toJson));
            return list;
        }
    
        /*
         * 根据json key排序
         */
        public static void sort(JsonElement je) {
            if (je.isJsonNull()) {
                return;
            }
    
            if (je.isJsonPrimitive()) {
                return;
            }
    
            if (je.isJsonArray()) {
                JsonArray array = je.getAsJsonArray();
                Iterator<JsonElement> it = array.iterator();
                while (it.hasNext()) {
                    sort(it.next());
                }
                return;
            }
    
            if (je.isJsonObject()) {
                Map<String, JsonElement> tm = new TreeMap(getComparator());
                for (Map.Entry<String, JsonElement> en : je.getAsJsonObject().entrySet()) {
                    tm.put(en.getKey(), en.getValue());
                }
    
                for (Map.Entry<String, JsonElement> en : tm.entrySet()) {
                    je.getAsJsonObject().remove(en.getKey());
                    je.getAsJsonObject().add(en.getKey(), en.getValue());
                    sort(en.getValue());
                }
                return;
            }
        }
    
        private static Comparator<String> getComparator() {
            return String::compareTo;
        }
    
       
    
    }
    

      

    用到的依赖包

    <dependency>
            <groupId>org.testng</groupId>
            <artifactId>testng</artifactId>
            <version>6.9.8</version>
     </dependency>
    <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.5</version>
    </dependency>
    <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>1.7.25</version>
    </dependency>
  • 相关阅读:
    Android H5混合开发(5):封装Cordova View, 让Fragment、弹框、Activity自由使用Cordova
    机器学习 AI 谷歌ML Kit 与苹果Core ML
    Android 设备唯一标识(多种实现方案)
    Android自定义控件:图形报表的实现(折线图、曲线图、动态曲线图)(View与SurfaceView分别实现图表控件)
    Android 禁止截屏、录屏 — 解决PopupWindow无法禁止录屏问题
    Android原生PDF功能实现:PDF阅读、PDF页面跳转、PDF手势伸缩、PDF目录树、PDF预览缩略图
    某助手验证码通信交互包分析
    IOS弓箭传说的插件开发
    微店APP协议简要分析
    Owhat sign参数分析
  • 原文地址:https://www.cnblogs.com/Eric-zhao/p/13154450.html
Copyright © 2011-2022 走看看