国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

JSON數(shù)據(jù)的差異對比工具(Java版)

這篇具有很好參考價值的文章主要介紹了JSON數(shù)據(jù)的差異對比工具(Java版)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

背景

說明

源碼

源碼走讀

其他


背景

? ? ? ? 之前有類似接口diff對比,數(shù)據(jù)對比的測試需求,涉及到j(luò)son格式的數(shù)據(jù)對比,調(diào)研了幾個大神們分享的代碼,選了一個最符合自己需求的研究了下。(可惜原文鏈接找不到了,原始作者看到了可以私信我下)

說明

這個對比方法,支持JsonObject和JsonArray類型的數(shù)據(jù)對比,支持:

  • 深度的對比:list變化(個數(shù)、內(nèi)容)、層級結(jié)構(gòu)變化
  • 字段的對比:新增、修改、刪除數(shù)據(jù)可察覺,能找到對應(yīng)的舊數(shù)據(jù)
  • 支持特定字段忽略對比

輸出的對比結(jié)果格式為:

json對比工具,java,json,開發(fā)語言,測試工具

源碼分為JsonCompareUtils, JsonAndMapSortUtils兩個類,對比入口是compareTwoJson方法

核心邏輯在JsonCompareUtils類中,JsonAndMapSortUtils主要做過程中的數(shù)據(jù)排序功能,相對獨立。

源碼

package com.xhzyqa.transcodetest.utils;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Stream;

public class JsonCompareUtils {

    //標(biāo)志位:對json報文中含有JsonArray類型的數(shù)據(jù)是否進(jìn)行排序
    private static boolean isSort;

    private Map<String, Object> oldJsonToMap = new LinkedHashMap<>();
    private Map<String, Object> newJsonToMap = new LinkedHashMap<>();

    //每一個實體里的排序字段
    private static Map<String, String> filedNameMap = new HashMap<>();

    static {
        filedNameMap.put("dogs", "dogNo");
        filedNameMap.put("cats", "catNo");
    }

    //可以跳過比對的字段
//    private static String[] skipCompareFiledNameMap = {"dogAge", "catAge", "catName"};
    private static String[] skipCompareFiledNameMap = {"key3"};

    /**
     * 兩json報文比對入口
     *
     * @param oldJsonStr
     * @param newJsonStr
     * @return
     */
    public String compareTwoJson(String oldJsonStr, String newJsonStr) {
        /**
         * 遞歸遍歷json對象所有的key-value,以map形式的path:value進(jìn)行存儲
         * 然后對兩個map進(jìn)行比較
         */
        convertJsonToMap(JSON.parseObject(oldJsonStr), "", false);
        convertJsonToMap(JSON.parseObject(newJsonStr), "", true);
        //獲取比較結(jié)果
        Map<String, Object> differenceMap = compareTwoMaps(oldJsonToMap, newJsonToMap);
        String diffJsonResult = convertMapToJson(differenceMap);
        return diffJsonResult;
    }

    /**
     * 將json數(shù)據(jù)轉(zhuǎn)換為map存儲--用于后續(xù)比較map
     *
     * @param json
     * @param root
     * @param isNew 區(qū)別新舊報文
     */
    private void convertJsonToMap(Object json, String root, boolean isNew) {
        if (json instanceof JSONObject) {
            JSONObject jsonObject = ((JSONObject) json);
            Iterator iterator = jsonObject.keySet().iterator();
            while (iterator.hasNext()) {
                Object key = iterator.next();
                Object value = jsonObject.get(key);
                String newRoot = "".equals(root) ? key + "" : root + "." + key;
                fillInResultMap(value, newRoot, isNew);
            }
        } else if (json instanceof JSONArray) {
            JSONArray jsonArray = (JSONArray) json;
            //將jsonArray進(jìn)行排序
            if (isSort) {
                //需要排序
                String sortEntityName = root.substring(root.lastIndexOf(".") + 1);
                String sortFiledName = filedNameMap.get(sortEntityName);//需要排序 獲取排序字段
                if (!StringUtils.isEmpty(sortFiledName)) {
                    jsonArray = JsonAndMapSortUtils.jsonArrayToSort(jsonArray, sortFiledName, true);
                }
            }
            final JSONArray jsonArray1 = jsonArray;
            Stream.iterate(0, integer -> integer + 1).limit(jsonArray1.size()).forEach(index -> {
                Object value = jsonArray1.get(index);
                String newRoot = "".equals(root) ? "[" + index + "]" : root + ".[" + index + "]";
                fillInResultMap(value, newRoot, isNew);
            });
        }
    }

    /**
     * 封裝json轉(zhuǎn)map后的數(shù)據(jù)
     *
     * @param value
     * @param newRoot
     * @param isNew   區(qū)別新舊json
     */
    public void fillInResultMap(Object value, String newRoot, boolean isNew) {
        if (value instanceof JSONObject || value instanceof JSONArray) {
            convertJsonToMap(value, newRoot, isNew);
        } else {
            //設(shè)置跳過比對的字段,直接不裝入map
            boolean check = ArrayUtils.contains(JsonCompareUtils.skipCompareFiledNameMap, newRoot);
            if (!check){
                if (!isNew) {
                    oldJsonToMap.put(newRoot, value);
                } else {
                    newJsonToMap.put(newRoot, value);
                }
            }
        }
    }

    /**
     * 比較兩個map,將不同的數(shù)據(jù)以map形式存儲并返回
     *
     * @param oldJsonMap
     * @param newJsonMap
     * @return
     */
    private Map<String, Object> compareTwoMaps(Map<String, Object> oldJsonMap, Map<String, Object> newJsonMap) {
        //1.將newJsonMap的不同數(shù)據(jù)裝進(jìn)oldJsonMap,同時刪除oldJsonMap中與newJsonMap相同的數(shù)據(jù)
        newJsonMap.forEach((k, v) -> {
            Map<String, Object> differenceMap = new HashMap<>();
            String lastFieldKey = k.substring(k.lastIndexOf(".") + 1);
//            boolean check = ArrayUtils.contains(JsonCompareUtils.skipCompareFiledNameMap, lastFieldKey);
//            if (!check){
            if (oldJsonMap.containsKey(k)) {
//                boolean check = ArrayUtils.contains(JsonCompareUtils.skipCompareFiledNameMap, lastFieldKey);
                Object oldValue = oldJsonMap.get(k);
                if (v.equals(oldValue)) {
                    oldJsonMap.remove(k);
                } else {
                    differenceMap.put("oldValue", oldValue);
                    differenceMap.put("newValue", v);
                    oldJsonMap.put(k, differenceMap);
                }
            } else {
                differenceMap.put("oldValue", "no exists " + k);
                differenceMap.put("newValue", v);
                oldJsonMap.put(k, differenceMap);
            }
//            }else {
//                oldJsonMap.remove(k);
//            }
        });
        //2.統(tǒng)一oldJsonMap中newMap不存在的數(shù)據(jù)的數(shù)據(jù)結(jié)構(gòu),便于解析
        oldJsonMap.forEach((k, v) -> {
            String lastFieldKey = k.substring(k.lastIndexOf(".") + 1);
//            boolean check = ArrayUtils.contains(JsonCompareUtils.skipCompareFiledNameMap, lastFieldKey);
//            if (!check && !(v instanceof Map)) {
            if (!(v instanceof Map)) {
                Map<String, Object> differenceMap = new HashMap<>();
                differenceMap.put("oldValue", v);
                differenceMap.put("newValue", "no exists " + k);
                oldJsonMap.put(k, differenceMap);
            }
        });
        return oldJsonMap;
    }

    /**
     * 將已經(jīng)找出不同數(shù)據(jù)的map根據(jù)key的層級結(jié)構(gòu)封裝成json返回
     *
     * @param map
     * @return
     */
    private String convertMapToJson(Map<String, Object> map) {
        JSONObject resultJSONObject = new JSONObject();
        for (Iterator<Map.Entry<String, Object>> it = map.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry<String, Object> item = it.next();
            String key = item.getKey();
            Object value = item.getValue();
            String[] paths = key.split("\\.");
            int i = 0;
            Object remarkObject = null;//用於深度標(biāo)識對象
            int indexAll = paths.length - 1;
            while (i <= paths.length - 1) {
                String path = paths[i];
                if (i == 0) {
                    //初始化對象標(biāo)識
                    if (resultJSONObject.containsKey(path)) {
                        remarkObject = resultJSONObject.get(path);
                    } else {
                        if (indexAll > i) {
                            if (paths[i + 1].matches("\\[[0-9]+\\]")) {
                                remarkObject = new JSONArray();
                            } else {
                                remarkObject = new JSONObject();
                            }
                            resultJSONObject.put(path, remarkObject);
                        } else {
                            resultJSONObject.put(path, value);
                        }
                    }
                    i++;
                    continue;
                }
                if (path.matches("\\[[0-9]+\\]")) {//匹配集合對象
                    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("\\[[0-9]+\\]")) {
                            while (((JSONArray) remarkObject).size() <= index) {
                                if (((JSONArray) remarkObject).size() == index) {
                                    ((JSONArray) remarkObject).add(index, new JSONArray());
                                } else {
                                    ((JSONArray) remarkObject).add(null);
                                }
                            }
                        } else {
                            while (((JSONArray) remarkObject).size() <= index) {
                                if (((JSONArray) remarkObject).size() == index) {
                                    ((JSONArray) remarkObject).add(index, new JSONObject());
                                } else {
                                    ((JSONArray) remarkObject).add(null);
                                }
                            }
                        }
                        remarkObject = ((JSONArray) remarkObject).get(index);
                    } else {
                        while (((JSONArray) remarkObject).size() <= index) {
                            if (((JSONArray) remarkObject).size() == index) {
                                ((JSONArray) remarkObject).add(index, value);
                            } else {
                                ((JSONArray) remarkObject).add(null);
                            }
                        }
                    }
                } else {
                    if (indexAll > i) {
                        if (paths[i + 1].matches("\\[[0-9]+\\]")) {
                            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 {
                        ((JSONObject) remarkObject).put(path, value);
                    }
                }
                i++;
            }
        }
        return JSON.toJSONString(resultJSONObject);
    }

    public boolean isSort() {
        return isSort;
    }

    public void setSort(boolean sort) {
        isSort = sort;
    }

    public static void main(String[] args) {
        String oldStr = "{key1:'aaa',key2:'bbb'}";
        String newStr = "{key1:'aaa',key2:'bbb',key3:'c'}";
        System.out.println(new JsonCompareUtils().compareTwoJson(oldStr, newStr));
        System.out.println("\n========測試復(fù)雜json的比對============");
    }

    /**
     * 測試類

    static class JsonCompareTest {
        public static void compareTest() {
            String oldJson = MakeJsonCompareDatas.getJsonDataOldStr();
            String newJson = MakeJsonCompareDatas.getJsonDataNewStr();

            //對json報文中含有JsonArray類型的數(shù)據(jù)是否進(jìn)行排序
            JsonCompareUtils.isSort = true;

            String compareResult = new JsonCompareUtils().compareTwoJson(oldJson, newJson);
            System.out.println("oldJson==>" + oldJson);
            System.out.println("newJson==>" + newJson);
            System.out.println("\nisSort==" + isSort + "-->compareResult==>\n" + compareResult);



        }
    }
     */
}


package com.xhzyqa.transcodetest.utils;


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import sun.misc.ASCIICaseInsensitiveComparator;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

public class JsonAndMapSortUtils {

    /**
     * map排序
     * @param map
     * @param keySort
     * @param <k>
     * @param <v>
     * @return
     */
    public static <k,v> List mapByKeyToSort(Map<k,v> map , final Comparator keySort){
        List<Map.Entry<k,v>> entryList = new ArrayList<Map.Entry<k, v>>(map.entrySet());
        Collections.sort(entryList, new Comparator<Map.Entry<k, v>>() {
            public int compare(Map.Entry<k, v> o1, Map.Entry<k, v> o2) {
                return keySort.compare(o1.getKey(),o2.getKey());
            }
        });
        //return (Map<k,v>)entryList.stream().collect(Collectors.toMap(Map.Entry<k,v>::getKey, Function.identity(), (key1, key2) -> key2));
        Map<String,String> afterToSortMap = new HashMap<>();
        /*for (Map.Entry<k,v> m : entryList){
            System.out.println(m.getKey()+"===>"+m.getValue());
        }*/
        System.out.println("排序=====");
        entryList.forEach(m->{
            System.out.println(m.getKey()+"===>"+m.getValue());
        });
        return entryList;
    }

    /**
     * JSONArray排序
     * @param jsonArray
     * @param fildName
     * @param isAsc
     * @return
     */
    public static JSONArray jsonArrayToSort(JSONArray jsonArray,final String fildName,final boolean isAsc){
        JSONArray afterSortJsonArray = new JSONArray();
        List<JSONObject> objectList = new ArrayList<JSONObject>();
        jsonArray.forEach(obj ->{
            objectList.add((JSONObject)obj);
        });
        Collections.sort(objectList, new Comparator<JSONObject>() {
            @Override
            public int compare(JSONObject o1, JSONObject o2) {
                String fildValueA = o1.getString(fildName);
                String fildValueB = o2.getString(fildName);
                if (isAsc)
                    return fildValueA.compareTo(fildValueB);
                return fildValueB.compareTo(fildValueA);
            }
        });
        objectList.forEach(obj->{
            afterSortJsonArray.add(obj);
        });
        return afterSortJsonArray;
    }

    /**
     *準(zhǔn)備map測試數(shù)據(jù)
     */
    public static Map<String,String> getMapData(){
        LinkedHashMap<String,String> map = new LinkedHashMap<>();
        map.put("key1","麥兜");
        map.put("key3","貝塔");
        map.put("key5","酥妮");
        map.put("key2","小H");
        map.put("key4","小O");
        return map;
    }
    /**
     *準(zhǔn)備json測試數(shù)據(jù)
     */
    public static JSONArray getJsonArrayData(){
        JSONArray jsonArray = new JSONArray();
        JSONObject jsonObject1 = new JSONObject();
        jsonObject1.put("userId","1001");
        jsonObject1.put("name","麥兜");
        jsonArray.add(jsonObject1);

        JSONObject jsonObject3 = new JSONObject();
        jsonObject3.put("userId","1003");
        jsonObject3.put("name","酥妮");
        jsonArray.add(jsonObject3);

        JSONObject jsonObject2 = new JSONObject();
        jsonObject2.put("userId","1002");
        jsonObject2.put("name","貝塔");
        jsonArray.add(jsonObject2);

        return jsonArray;
    }

    public static void main(String[] args) {
        Map<String,String> map = JsonAndMapSortUtils.getMapData();
        JSONArray jsonArray = JsonAndMapSortUtils.getJsonArrayData();
        List afterSortMap = JsonAndMapSortUtils.mapByKeyToSort(map,new ASCIICaseInsensitiveComparator());

        JSONArray afterSortJsonArray_isAsc = JsonAndMapSortUtils.jsonArrayToSort(jsonArray,"userId",true);
        JSONArray afterSortJsonArray_noAsc = JsonAndMapSortUtils.jsonArrayToSort(jsonArray,"userId",false);

        System.out.println("map排序前:"+map);
        System.out.println("map排序后:"+afterSortMap+"\n");

        System.out.println("JsonArray排序前:"+jsonArray);
        System.out.println("JsonArray排序后==》升序:"+afterSortJsonArray_isAsc);
        System.out.println("JsonArray排序后==》降序:"+afterSortJsonArray_noAsc);
    }


}

源碼走讀

整個源碼調(diào)用鏈路如下圖,簡單來說過程就是:object拆分解析-新舊數(shù)據(jù)逐個對比-結(jié)果信息組裝三個步驟

json對比工具,java,json,開發(fā)語言,測試工具

其他

原始代碼中有些小bug,已修復(fù)。目前這個工具主要被我拿來用在了一個接口數(shù)據(jù)對比工具中,來檢測迭代前后的接口協(xié)議數(shù)據(jù)變更,以完善迭代變更范圍來確認(rèn)測試范圍文章來源地址http://www.zghlxwxcb.cn/news/detail-539396.html

到了這里,關(guān)于JSON數(shù)據(jù)的差異對比工具(Java版)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • java hutool工具類處理json的常用方法

    Hutool 提供了豐富的 JSON 處理工具類,包括 JSON 字符串的解析、生成、對象與 JSON 字符串的轉(zhuǎn)換等。以下是 Hutool 中關(guān)于 JSON 的常用方法: JSON 字符串的解析與生成: JSONUtil.parseObj(jsonStr) :將 JSON 字符串解析為 JSONObject 對象。 JSONUtil.parseArray(jsonStr) :將 JSON 字符串解析為 JSON

    2024年04月17日
    瀏覽(18)
  • Java工具類——json字符串格式化處理

    Java工具類——json字符串格式化處理

    在我們拿到一團未經(jīng)格式化的json字符串時,非常不方便查看,比如這樣 因此隨手寫了個工具類用來格式化json。注意,原json字符串必須語法無誤,并且不包含換行、空格、縮進(jìn)等,否則會保留下來。 ok廢話不多說上代碼 運行后效果

    2024年01月17日
    瀏覽(29)
  • Java 工具類之JSON key根據(jù)ASCII排序

    參數(shù)按照KEY值進(jìn)行字典序排序(按照KEY值的ASCII碼從小到大),并用作為各參數(shù)之間的分隔符將參數(shù)拼接成字符串。這里用到了SortedMap,復(fù)制以下代碼開箱即用~

    2024年02月12日
    瀏覽(15)
  • mysql 5.7 json 類型 json 數(shù)組類型 普通字符串類型 10w數(shù)據(jù) 查詢速度差異

    mysql 5.7 json 類型 json 數(shù)組類型 普通字符串類型 10w數(shù)據(jù) 查詢速度差異

    建表語句ddl 10w 數(shù)據(jù) 插入 存儲過程 ?json 類型 vs 普通字符串類型 建表語句ddl CREATE TABLE tb_json_array_test ( id INT NOT NULL AUTO_INCREMENT, user_no VARCHAR(100), user_name VARCHAR(100), score INT, create_time date, update_time date, remark VARCHAR(100), field1 VARCHAR(100), field2 VARCHAR(100), field3 VARCHAR(100), field4 VARCHAR(

    2024年02月04日
    瀏覽(25)
  • 用反射實現(xiàn)自定義Java對象轉(zhuǎn)化為json工具類

    用反射實現(xiàn)自定義Java對象轉(zhuǎn)化為json工具類

    傳入一個object類型的對象 獲取該對象的class類 getFields方法獲取該類的所有屬性 對屬性進(jìn)行遍歷,并且拼接成Json格式的字符串,注意:通過屬性名來推斷方法名 獲取Method實例 通過invoke方法調(diào)用 以User類進(jìn)行測試 ??

    2024年02月11日
    瀏覽(21)
  • Java后端開發(fā)——Ajax、jQuery和JSON

    Java后端開發(fā)——Ajax、jQuery和JSON

    Ajax全稱是Asynchronous Javascript and XML,即異步的JavaScript和 XML。Ajax是一種Web應(yīng)用技術(shù),該技術(shù)是在JavaScript、DOM、服務(wù)器配合下,實現(xiàn)瀏覽器向服務(wù)器發(fā)送異步請求。 Ajax異步請求方式不向服務(wù)器發(fā)出請求,會得到數(shù)據(jù)后再更新頁面(通過DOM操作修改頁面內(nèi)容),整個過程不會發(fā)

    2024年02月03日
    瀏覽(23)
  • 如何使用Java處理JSON數(shù)據(jù)?

    在Java中,您可以使用許多庫來處理JSON數(shù)據(jù)。以下是使用一種常見的庫 Gson 的示例: 首先,確保您已經(jīng)將 Gson 庫添加到您的項目中。您可以在 Maven 中添加以下依賴項: 導(dǎo)入 Gson 類: 創(chuàng)建一個 Gson 實例: 將 JSON 字符串轉(zhuǎn)換為 Java 對象,使用? fromJson() ?方法: 上面代碼中,將

    2024年02月15日
    瀏覽(27)
  • java 獲取request中json數(shù)據(jù)

    java 獲取request中json數(shù)據(jù)

    功能簡介: ? ? ? ? Java 從 HttpServletRequest?中獲取前端傳輸過來的json數(shù)據(jù) 效果展示: 請求示例: post: 127.0.0.1:8081/getRequestJson 代碼示例: 拓展: ?

    2024年02月12日
    瀏覽(18)
  • Java開發(fā)者的Python進(jìn)修指南:JSON利器之官方j(luò)son庫、demjson和orjson的實用指南

    JSON作為目前最流行的傳輸格式,在Python中也有相應(yīng)的實現(xiàn)方式。由于JSON格式的文本可以跨平臺并且簡單易用,因此被廣泛傳播。因此,我們今天的主要討論內(nèi)容是如何熟練地應(yīng)用Python的JSON庫來處理將JSON映射到文本,以及如何從文本映射到對象中?,F(xiàn)在,讓我們開始探討這個

    2024年01月23日
    瀏覽(17)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包