鏡之Json Compare Diff

前言

“鏡” 寓意是凡事都有兩面性,Json對比也不例外!

因公司業(yè)務(wù)功能當(dāng)中有一個履歷的功能,它有多個版本的JSON數(shù)據(jù)需要對比出每個版本的不同差異節(jié)點并且將差異放置在一個新的JSON當(dāng)中原有結(jié)構(gòu)不能變動,差異節(jié)點使用數(shù)組對象的形式存儲,前端點擊標(biāo)紅即可顯示多個版本的節(jié)點差異數(shù)據(jù)如下圖

banner
履歷查看

示例

// JSON One
{ 
    "employee":
    {
        "id": "1212",
        "fullName":"John Miles",
        "age": 34,
        "contact":
        {
            "email": "john@xyz.com",
            "phone": "9999999999"
        }
    }
}

// Json Two
{
    "employee":
    {
        "id": "1212",
        "ae86": "12162",
        "age": 34,
        "fullName": "John Miles111",
        "contact":
        {
            "email": "john@xyz.com",
            "phone": "我是改了的",
            "668": "999999991199"
        }
    }
}

可以看到 employee.ae86 是新增的窍帝。contact.668 也是新增的 phone 字段是修改了的

對比后的Json

// 獲取差異的節(jié)點 使用數(shù)組對象表示
{
    "employee/fullName/": [{
        "old": "John Miles"
    }, {
        "new": "John Miles111"
    }],
    "employee/contact/phone/": [{
        "old": "9999999999"
    }, {
        "new": "我是改了的"
    }],
    "employee/contact/668": [{
        "new": "999999991199"
    }],
    "employee/ae86": [{
        "new": "12162"
    }]
}

// 將差異節(jié)點的數(shù)據(jù)覆蓋上去

{
  "employee" : {
    "id" : "1212",
    "fullName" : [ {
      "old" : "John Miles"
    }, {
      "new" : "John Miles111"
    } ],
    "age" : 34,
    "contact" : {
      "email" : "john@xyz.com",
      "phone" : [ {
        "old" : "9999999999"
      }, {
        "new" : "我是改了的"
      } ],
      "668" : [ {
        "new" : "999999991199"
      } ]
    },
    "ae86" : [ {
      "new" : "12162"
    } ]
  }
}

實現(xiàn)

一、得到差異點Map

package com.yby6;


import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.lang3.ObjectUtils;

import java.io.IOException;
import java.util.*;

/**
 * @author Yang Shuai
 * Create By 2023/8/26
 */

public class JsonComparerUtils2 {
    static ObjectMapper mapper = new ObjectMapper();

    public static void main(String[] args) {

        String s1 = "{ \n" +
                "    \"employee\":\n" +
                "    {\n" +
                "        \"id\": \"1212\",\n" +
                "        \"fullName\":\"John Miles\",\n" +
                "        \"age\": 34,\n" +
                "        \"contact\":\n" +
                "        {\n" +
                "            \"email\": \"john@xyz.com\",\n" +
                "            \"phone\": \"9999999999\"\n" +
                "        }\n" +
                "    }\n" +
                "}";
        String s2 = "{\n" +
                "    \"employee\":\n" +
                "    {\n" +
                "        \"id\": \"1212\",\n" +
                "        \"ae86\": \"12162\",\n" +
                "        \"age\": 34,\n" +
                "        \"fullName\": \"John Miles111\",\n" +
                "        \"contact\":\n" +
                "        {\n" +
                "            \"email\": \"john@xyz.com\",\n" +
                "            \"phone\": \"我是改了的\",\n" +
                "            \"668\": \"999999991199\"\n" +
                "        }\n" +
                "    }\n" +
                "}";
        try {

            // 將json轉(zhuǎn)Json節(jié)點樹
            JsonNode node1 = mapper.readTree(s1);
            JsonNode node2 = mapper.readTree(s2);

            List<String> ignoreKey = new ArrayList<>();

            // 獲取兩個JSON之間的差異
            Map<String, Object> nodesDiff = getNodesDiff(node1, node2,
                    "", ignoreKey);
            System.out.println(mapper.writeValueAsString(nodesDiff));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }


    /**
     * 得到節(jié)點差異
     *
     * @param node1     node1
     * @param node2     node2
     * @param path      路徑
     * @param ignoreKey 忽略關(guān)鍵
     * @return {@link Map}<{@link String}, {@link Object}>
     */
    private static Map<String, Object> getNodesDiff(JsonNode node1, JsonNode node2, String path, List<String> ignoreKey) {
        Map<String, Object> diff = new LinkedHashMap<>();

        String[] split = path.split("/");
        String filed = split[split.length - 1];


        if (!node1.getNodeType().equals(node2.getNodeType())) {
            addToMap(path, node1, node2, diff, "update");
        } else {
            switch (node1.getNodeType()) {
                case OBJECT:

                    if (node1.isObject() && !node1.isEmpty()) {
                        for (Iterator<String> it = node1.fieldNames(); it.hasNext(); ) {
                            String fieldName = it.next();

                            JsonNode childNode1 = node1.get(fieldName);
                            JsonNode childNode2 = node2.get(fieldName);

                            // 忽略指定字段不對比
                            if (ignoreKey.contains(fieldName)) {
                                continue;
                            }

                            if (childNode2 != null) {
                                Map<String, Object> nestedDiff = getNodesDiff(childNode1, childNode2, path + fieldName + "/", ignoreKey);
                                if (!nestedDiff.isEmpty()) {
                                    diff.putAll(nestedDiff);
                                }
                            } else {
                                // 舊的存在新的則不存在表示刪除
                                addToMap(path + fieldName, childNode1, childNode1, diff, "delete");
                            }
                        }

                        for (Iterator<String> it = node2.fieldNames(); it.hasNext(); ) {
                            String fieldName = it.next();
                            if (ignoreKey.contains(fieldName)) {
                                continue;
                            }
                            // 如果舊的沒有這個數(shù)據(jù)那么表示新增
                            if (node1.get(fieldName) == null) {
                                addToMap(path + fieldName, null, node2.get(fieldName), diff, "add");
                            }
                        }
                    }


                    break;
                case ARRAY:
                    // 判斷兩個數(shù)組的長度不一樣則需要將兩個數(shù)組的長度補(bǔ)齊
                    if (node1.size() > 0 && node2.size() > 0 && node1.size() != node2.size()) {

                        try {
                            String m1 = mapper.writeValueAsString(node1);
                            String m2 = mapper.writeValueAsString(node2);

                            List list1 = mapper.readValue(m1, List.class);
                            List list2 = mapper.readValue(m2, List.class);


                            if (list1.size() > list2.size()) {

                                for (int i = list2.size(); i < list1.size(); i++) {
                                    String o = mapper.writeValueAsString(list1.get(i));
                                    JsonNode jsonNode = mapper.readTree(o);
                                    // 清空的
                                    clearNodeValues(jsonNode, ignoreKey);
                                    // 將jsonNode2添加到j(luò)sonNode1中
                                    ((ArrayNode) node2).add(jsonNode);
                                }
                            } else {
                                for (int i = list1.size(); i < list2.size(); i++) {
                                    String o = mapper.writeValueAsString(list2.get(i));
                                    JsonNode jsonNode = mapper.readTree(o);
                                    // 清空的
                                    clearNodeValues(jsonNode, ignoreKey);
                                    ((ArrayNode) node1).add(jsonNode);
                                }
                            }


                            // 排序數(shù)組

                            List<JsonNode> firstList = mapper.readValue(node1.traverse(), new TypeReference<List<JsonNode>>() {
                            });
                            List<JsonNode> secondList = mapper.readValue(node2.traverse(), new TypeReference<List<JsonNode>>() {
                            });


                            // 補(bǔ)齊后遞歸對比
                            for (int i = 0; i < firstList.size(); i++) {
                                Map<String, Object> nestedDiff = getNodesDiff(firstList.get(i), secondList.get(i), path + "[" + i + "]/", ignoreKey);
                                if (!nestedDiff.isEmpty()) {
                                    diff.putAll(nestedDiff);
                                }
                            }


                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }

                    } else {
                        // 判斷數(shù)組里面是不是對象
                        if (node1.size() > 0 && node1.get(0).getNodeType().equals(JsonNodeType.OBJECT)) {
                            for (int i = 0; i < node1.size(); i++) {
                                if (ignoreKey.contains(filed)) {
                                    break;
                                }
                                Map<String, Object> nestedDiff = getNodesDiff(node1.get(i), node2.get(i), path + "[" + i + "]/", ignoreKey);
                                if (!nestedDiff.isEmpty()) {
                                    diff.putAll(nestedDiff);
                                }
                            }
                        } else {
                            if (!node1.equals(node2)) {
                                if (ignoreKey.contains(filed)) {
                                    break;
                                }
                                addToMap(path, node1, node2, diff, "update");
                            }
                        }
                    }
                    break;
                case STRING:
                case BOOLEAN:
                case NUMBER:
                    if (ignoreKey.contains(filed)) {
                        break;
                    }

                    // 如果新的為空則為刪除
                    if (ObjectUtils.isEmpty(node2)) {
                        addToMap(path, node1, node2, diff, "delete");
                    }

                    if (!node1.equals(node2)) {
                        addToMap(path, node1, node2, diff, "update");
                    }

                    break;
                default:
                    throw new IllegalArgumentException("Unsupported JSON type:" + node1.getNodeType().name());
            }
        }

        return diff;
    }


    /**
     * 清空節(jié)點參數(shù)
     *
     * @param node 節(jié)點
     */
    private static void clearNodeValues(JsonNode node, List<String> ignoreKey) {
        // 忽略部分清空
        if (node.isObject()) {
            ObjectNode objectNode = (ObjectNode) node;
            objectNode.fields().forEachRemaining(entry -> {
                if (!ignoreKey.contains(entry.getKey())) {
                    objectNode.replace(entry.getKey(), null);
                }
            });
        } else if (node.isArray()) {
            for (JsonNode childNode : node) {
                clearNodeValues(childNode, ignoreKey);
            }
        }
    }


    /**
     * 將兩個json的差異添加到Map
     *
     * @param path     路徑
     * @param oldValue 舊值
     * @param newValue 新值
     * @param diff     diff
     */
    private static void addToMap(String path, JsonNode oldValue, JsonNode newValue, Map<String, Object> diff, String diffType) {
        List<Object> values = new ArrayList<>();
        HashMap<String, Object> map = new HashMap<>();
        map.put("old", oldValue != null ? getContent(oldValue) : "");
        map.put("new", newValue != null ? getContent(newValue) : "");
        map.put("diffType", diffType);
        values.add(map);
        diff.put(path, values.toArray(new Object[0]));
    }

    /**
     * 獲取內(nèi)容
     *
     * @param node 節(jié)點
     * @return {@link Object}
     */
    private static Object getContent(JsonNode node) {
        if (node.isBoolean()) {
            return node.asBoolean();
        } else if (node.isNumber()) {
            return node.asInt();
        } else if (node.isTextual()) {
            return node.asText();
        } else if (node.isObject()) {
            Map<String, Object> obj = new LinkedHashMap<>();
            for (Iterator<String> it = node.fieldNames(); it.hasNext(); ) {
                String propName = it.next();
                obj.put(propName, getContent(node.get(propName)));
            }
            return obj;
        } else if (node.isArray()) {
            ArrayNode array = (ArrayNode) node;
            Object[] contents = new Object[array.size()];
            for (int i = 0; i < array.size(); i++) {
                contents[i] = getContent(array.get(i));
            }
            return contents;
        } else if (node.isNull()) {
            return null;
        } else {
            throw new UnsupportedOperationException("不支持的 JSON 類型:" + node.getNodeType().name());
        }
    }

測試輸出

測試
{
    "employee/fullName/": [{
        "new": "John Miles111",
        "old": "John Miles",
        "diffType": "update"
    }],
    "employee/contact/phone/": [{
        "new": "我是改了的",
        "old": "9999999999",
        "diffType": "update"
    }],
    "employee/contact/668": [{
        "new": "999999991199",
        "old": "",
        "diffType": "add"
    }],
    "employee/ae86": [{
        "new": "12162",
        "old": "",
        "diffType": "add"
    }]
}

獲取差異代碼講解

這段代碼是一個處理兩個 JSON 節(jié)點之間差異的方法诽偷,以及一些輔助方法坤学。下面我將解釋每個方法的作用和代碼邏輯:

getNodesDiff 方法

描述

該方法用于比較兩個 JSON 節(jié)點(node1node2)之間的差異,包括子節(jié)點差異报慕,并返回一個表示差異的 Map深浮。

方法簽名

private static Map<String, Object> getNodesDiff(JsonNode node1, JsonNode node2, String path, List<String> ignoreKey)

代碼解釋

  • diff 是一個用于存儲差異的 LinkedHashMap
  • 首先眠冈,它根據(jù)路徑 path 中的最后一個部分(field)來確定節(jié)點的類型飞苇。
  • 然后,它檢查 node1node2 的節(jié)點類型是否相同蜗顽,如果不同布卡,將差異添加到 diff 中。
  • 如果節(jié)點類型相同雇盖,則根據(jù)節(jié)點類型進(jìn)行處理忿等,包括對象、數(shù)組崔挖、字符串贸街、布爾值和數(shù)字類型庵寞。
  • 對于對象類型,它遞歸地比較對象的字段薛匪,同時考慮了一些特殊情況皇帮,例如忽略指定的字段和 isValid 字段為 0 的情況。
  • 對于數(shù)組類型蛋辈,它首先檢查數(shù)組長度是否不一致,如果不一致将谊,則嘗試將兩個數(shù)組的長度補(bǔ)齊冷溶,然后遞歸比較數(shù)組元素。如果數(shù)組元素是對象類型尊浓,也會遞歸比較對象逞频。
  • 對于其他基本數(shù)據(jù)類型,它會直接比較節(jié)點的值栋齿,如果不同苗胀,將差異添加到 diff 中。

clearNodeValues 方法

描述

這是一個輔助方法瓦堵,用于清空節(jié)點的值基协,但保留節(jié)點結(jié)構(gòu)。

方法簽名

private static void clearNodeValues(JsonNode node, List<String> ignoreKey)

代碼解釋

  • 如果節(jié)點是對象類型菇用,則清空對象中指定的字段澜驮,但忽略 ignoreKey 中的字段。
  • 如果節(jié)點是數(shù)組類型惋鸥,則遞歸地清空數(shù)組元素的值杂穷,但保留數(shù)組結(jié)構(gòu)。

addToMap 方法

描述

這是一個輔助方法卦绣,用于將差異信息添加到差異 Map 中耐量。

方法簽名

private static void addToMap(String path, JsonNode oldValue, JsonNode newValue, Map<String, Object> diff, String diffType)

代碼解釋

  • 該方法將差異信息以指定的格式添加到 diff 中,包括路徑 path滤港、舊值 oldValue廊蜒、新值 newValue 和差異類型 diffType

getContent 方法

描述

這是一個輔助方法溅漾,用于從 JsonNode 中提取內(nèi)容劲藐。

方法簽名

private static Object getContent(JsonNode node)

代碼解釋

  • 該方法根據(jù) JsonNode 的類型提取內(nèi)容,可能是布爾值樟凄、整數(shù)聘芜、字符串、對象缝龄、數(shù)組或 null 值汰现。
  • 對于對象和數(shù)組類型挂谍,它遞歸提取內(nèi)容并返回。

二瞎饲、合并

    /**
     * 將差異應(yīng)用到指定的 JSON 字符串口叙,并返回處理后的字符串。
     *
     * @param json 要應(yīng)用差異的原始 JSON 字符串
     * @param diff 差異內(nèi)容嗅战,即 {@link #getNodesDiff} 返回的 Map 對象
     * @return 經(jīng)過差異處理后的 JSON 字符串
     */
    public static String applyDiff(String json, Map<String, Object> diff) throws IOException {
        JsonNode node = mapper.readTree(json);
        for (Map.Entry<String, Object> entry : diff.entrySet()) {
            String[] path = entry.getKey().split("/");
            JsonNode parentNode = node;
            for (int i = 0; i < path.length - 1; i++) {
                // 如果是null則跳過
                if (parentNode == null) {
                    continue;
                }
                // 如果該節(jié)點是數(shù)組那么解析一下
                if (parentNode.isArray()) {
                    int index = getIndexFromPath(path[i]);
                    parentNode = parentNode.get(index);
                } else {
                    parentNode = parentNode.get(path[i]);
                }
            }

            // 如果拿到的父節(jié)點是null則跳過
            if (parentNode == null) {
                continue;
            }

            String propertyName = path[path.length - 1];
            JsonNode childNode = parentNode.get(propertyName);


            if (entry.getValue() == null) {
                if (parentNode.isArray()) {
                    ((ArrayNode) parentNode).remove(Integer.parseInt(propertyName.substring(1, propertyName.length() - 1)));
                } else {
                    ((ObjectNode) parentNode).remove(propertyName);
                }
            } else {
                Object value = entry.getValue();
                // 是否是數(shù)組
                if (ArrayUtil.isArray(value)) {
//                    ArrayNode arrayNode = mapper.createArrayNode(); // 新建一個空的數(shù)組節(jié)點
//                    arrayNode.addPOJO(value);
                    ObjectMapper objectMapper = new ObjectMapper();
                    JsonNode arrayNode = objectMapper.valueToTree(value);
//                    Object[] arr = (Object[]) value;
//                    for (Object item : arr) {
//                        if (item != null) {
//                            // 將數(shù)組元素依次加入新建的數(shù)組節(jié)點中妄田,不需要處理逗號問題
//                            arrayNode.addPOJO(item);
//                        }
//                    }
                    if (childNode != null && !childNode.isMissingNode()) { // 已經(jīng)存在該屬性,需要替換
                        ((ObjectNode) parentNode).replace(propertyName, arrayNode);
                    } else { // 不存在該屬性驮捍,直接應(yīng)用差異
                        // 如果父節(jié)點是數(shù)組疟呐,在數(shù)組末尾添加新元素
                        // 如果父節(jié)點是對象,在該對象中添加新屬性东且,值為空
                        if (parentNode.isArray()) {
                            int position = 0;
                            if (StringUtils.isNotBlank(propertyName)) {
                                position = Integer.parseInt(propertyName.substring(1, propertyName.length() - 1));
                            }

                            while (position > parentNode.size()) {
                                ((ArrayNode) parentNode).add(mapper.createObjectNode().put("", ""));
                            }
                            ((ArrayNode) parentNode).add(arrayNode);
                        } else {
                            ((ObjectNode) parentNode).set(propertyName, arrayNode);
                        }
                    }
                } else {
                    String newValue = entry.getValue().toString();
                    if (childNode == null || childNode.isNull() || childNode.isMissingNode()) {
                        if (parentNode.isArray()) { // 如果父節(jié)點是數(shù)組启具,在數(shù)組末尾添加新元素
                            ((ArrayNode) parentNode).add(mapper.createObjectNode().put(propertyName, ""));
                        } else { // 如果父節(jié)點是對象,在該對象中添加新屬性珊泳,值為空
                            ((ObjectNode) parentNode).put(propertyName, "");
                        }
                        childNode = parentNode.get(propertyName);
                    }
                    if (childNode.isValueNode()) {
                        if (childNode.isBoolean()) {
                            ((ObjectNode) parentNode).put(propertyName, Boolean.parseBoolean(newValue));
                        } else if (childNode.isIntegralNumber()) {
                            ((ObjectNode) parentNode).put(propertyName, newValue);
                        } else if (childNode.isFloatingPointNumber()) {
                            ((ObjectNode) parentNode).put(propertyName, Double.parseDouble(newValue));
                        } else if (childNode.isTextual()) {
                            try {
                                ((ObjectNode) parentNode).put(propertyName, newValue.substring(1, newValue.length() - 1)); // 去掉 JSON 字符串外層的雙引號
                            } catch (Exception e) {
                                ((ObjectNode) parentNode).put(propertyName, newValue);
                            }
                        }
                    } else {
                        ((ObjectNode) parentNode).set(propertyName, mapper.readTree(newValue));
                    }
                }
            }
        }
        return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(node);
    }


    /**
     * 移除方括號并將剩余字符串解析為整數(shù)索引
     *
     * @param path 路徑
     * @return int
     */
    private static int getIndexFromPath(String path) {
        return Integer.parseInt(path.substring(1, path.length() - 1));
    }

測試差異應(yīng)用

測試差異應(yīng)用
{
    "employee": {
        "id": "1212",
        "ae86": [{
            "new": "12162",
            "old": "",
            "diffType": "add"
        }],
        "age": 34,
        "fullName": [{
            "new": "John Miles111",
            "old": "John Miles",
            "diffType": "update"
        }],
        "contact": {
            "email": "john@xyz.com",
            "phone": [{
                "new": "我是改了的",
                "old": "9999999999",
                "diffType": "update"
            }],
            "668": [{
                "new": "999999991199",
                "old": "",
                "diffType": "add"
            }]
        }
    }
}

差異應(yīng)用代碼講解

applyDiff 方法

描述

該方法將差異應(yīng)用到指定的 JSON 字符串鲁冯,并返回處理后的字符串。它接受一個原始的 JSON 字符串和一個差異的 Map色查,通常是從 getNodesDiff 方法獲取的薯演。

方法簽名

public static String applyDiff(String json, Map<String, Object> diff) throws IOException

代碼解釋

  • 該方法首先使用 Jackson ObjectMapper mapper 將輸入的 JSON 字符串 json 解析為一個 JsonNode 對象。
  • 遍歷差異的 Map 中的每個條目秧了,每個條目表示要應(yīng)用到 JSON 的變更涣仿。
  • 對于每個條目,它通過 '/' 來分割條目的鍵(表示 JSON 內(nèi)的路徑)示惊,然后按照路徑迭代 JSON 結(jié)構(gòu)好港,更新當(dāng)前節(jié)點指針。
  • 如果父節(jié)點為 null 或缺失米罚,會跳過當(dāng)前迭代钧汹。
  • 根據(jù)條目的值是否為 null,它要么移除一個節(jié)點录择,要么更新它:
- 如果值為 null拔莱,它會從 JSON 結(jié)構(gòu)中移除節(jié)點。如果父節(jié)點是數(shù)組隘竭,則移除指定索引處的元素塘秦;否則,從對象中移除指定屬性动看。
- 如果值不為 null尊剔,它會檢查值是否為數(shù)組。如果是數(shù)組菱皆,它會創(chuàng)建一個新的 JSON 數(shù)組節(jié)點须误,并根據(jù)屬性是否已存在挨稿,要么替換要么添加到父節(jié)點中。如果值不是數(shù)組京痢,則根據(jù)其類型(布爾值奶甘、數(shù)字、字符串或 JSON 對象)更新 JSON 結(jié)構(gòu)中的屬性祭椰。
  • 最后臭家,它使用 mapper 將修改后的 JsonNode 轉(zhuǎn)換回 JSON 字符串,并返回結(jié)果的 JSON 字符串方淤。

getIndexFromPath 方法

描述

這是一個私有的實用方法钉赁,用于移除字符串中的方括號,并將剩余的字符串解析為整數(shù)索引臣淤。

方法簽名

private static int getIndexFromPath(String path)

代碼解釋

  • 該方法以一個 path 字符串作為輸入。
  • 它移除 path 字符串的首尾字符(假設(shè)它們是方括號)窃爷,然后將剩余的子串解析為整數(shù)索引邑蒋。
  • 解析后的整數(shù)索引被返回。

over

最后

本期結(jié)束咱們下次再見??~

按厘,關(guān)注我不迷路医吊,如果本篇文章對你有所幫助,或者你有什么疑問逮京,歡迎在評論區(qū)留言卿堂,我一般看到都會回復(fù)的。大家點贊支持一下喲~ ??

【選題思路】

基于兩串不同的JSON數(shù)據(jù)進(jìn)行對比出來差異再將差異應(yīng)用到最新的Json字符串當(dāng)中.

【寫作提綱】

一懒棉、前言

因公司業(yè)務(wù)功能當(dāng)中有一個履歷的功能,它有多個版本的JSON數(shù)據(jù)需要對比出每個版本的不同差異節(jié)點并且將差異放置在一個新的JSON當(dāng)中原有結(jié)構(gòu)不能變動,差異節(jié)點使用數(shù)組對象的形式存儲,前端點擊標(biāo)紅即可顯示多個版本的節(jié)點差異數(shù)據(jù)

二草描、示例

介紹兩個Json的差異對比效果

三、實現(xiàn)

先得到兩個Json的差異節(jié)點集合策严、接著在最新的Json中轉(zhuǎn)換json節(jié)點對象進(jìn)行判斷每個節(jié)點的字段是否符合則插入到對應(yīng)的字段當(dāng)中!

本文由mdnice多平臺發(fā)布

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末穗慕,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子妻导,更是在濱河造成了極大的恐慌逛绵,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件倔韭,死亡現(xiàn)場離奇詭異术浪,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)寿酌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門胰苏,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人醇疼,你說我怎么就攤上這事碟联〖嗣溃” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵鲤孵,是天一觀的道長壶栋。 經(jīng)常有香客問我,道長普监,這世上最難降的妖魔是什么贵试? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮凯正,結(jié)果婚禮上毙玻,老公的妹妹穿的比我還像新娘。我一直安慰自己廊散,他們只是感情好桑滩,可當(dāng)我...
    茶點故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著允睹,像睡著了一般运准。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上缭受,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天胁澳,我揣著相機(jī)與錄音,去河邊找鬼米者。 笑死韭畸,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蔓搞。 我是一名探鬼主播胰丁,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼喂分!你這毒婦竟也來了隘马?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤妻顶,失蹤者是張志新(化名)和其女友劉穎酸员,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體讳嘱,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡幔嗦,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了沥潭。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片邀泉。...
    茶點故事閱讀 38,137評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出汇恤,到底是詐尸還是另有隱情庞钢,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布因谎,位于F島的核電站基括,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏财岔。R本人自食惡果不足惜风皿,卻給世界環(huán)境...
    茶點故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望匠璧。 院中可真熱鬧桐款,春花似錦、人聲如沸夷恍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽酿雪。三九已至遏暴,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間执虹,已是汗流浹背拓挥。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工唠梨, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留袋励,地道東北人。 一個月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓当叭,卻偏偏與公主長得像茬故,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子蚁鳖,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 一磺芭、簡介 json-diff是一款強(qiáng)大的,由java編寫的json差異發(fā)現(xiàn)工具醉箕。他可以發(fā)現(xiàn)任何結(jié)構(gòu)的json差異钾腺,...
    洋芋炒土豆絲閱讀 573評論 1 0
  • 一、摘要 今天推薦的是一款java中讥裤,對比兩個json-diff對象是否一致的工具包 json-diff[http...
    洋芋炒土豆絲閱讀 506評論 0 0
  • By Long Luo 引言 NOKIA 有句著名的廣告語:“科技以人為本”己英。任何技術(shù)都是為了滿足人的生產(chǎn)生活需要...
    Coder_LL閱讀 285評論 0 1
  • 前言 最近在開發(fā)過程中遇到了需要diff文件內(nèi)容或者大json的業(yè)務(wù)場景间螟,發(fā)現(xiàn)了一個比較好用且經(jīng)典的js庫diff...
    廣蘭路地鐵閱讀 18,852評論 0 5
  • 1、各自定義 XML擴(kuò)展標(biāo)記語言 (Extensible Markup Language, XML) ,用于標(biāo)記電...
    插兜閱讀 634評論 0 2