Java 实现 JSON对象差异化对比


前言

请各大网友尊重本人原创知识分享,谨记本人博客:南国以南i


提示:以下是本篇文章正文内容,下面案例可供参考

简介

在Java中,对比两个JSON对象并输出它们的不同点,可以通过使用第三方库如 org.json、com.fasterxml.jackson.databind(Jackson)或com.alibaba.fastjson(Fastjson) 来实现。这些库提供了丰富的API来处理JSON数据,包括解析、生成和比较JSON对象。

简化版本

使用 com.alibaba.fastjson 库来对比两个JSON对象并输出不同点的示例代码:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;

import java.util.Iterator;
import java.util.Map;

public class JsonDifference {

    public static void main(String[] args) {
        // 定义两个JSON对象
        String json1Str = "{\"name\":\"John\",\"age\":30,\"city\":\"New York\"}";
        String json2Str = "{\"name\":\"John\",\"age\":31,\"city\":\"Los Angeles\"}";

        // 将字符串解析为JSON对象
        JSONObject json1 = JSON.parseObject(json1Str);
        JSONObject json2 = JSON.parseObject(json2Str);

        // 调用方法比较两个JSON对象
        compareJsonObjects(json1, json2);
    }

    public static void compareJsonObjects(JSONObject json1, JSONObject json2) {
        // 获取json1的键集合
        Iterator<String> keys1 = json1.keySet().iterator();
        while (keys1.hasNext()) {
            String key = keys1.next();
            // 检查json2是否包含相同的键
            if (json2.containsKey(key)) {
                // 如果两个键都存在,则比较它们的值
                Object value1 = json1.get(key);
                Object value2 = json2.get(key);
                if (!value1.equals(value2)) {
                    System.out.println("Difference found at key \"" + key + "\": " +
                            "json1 value = " + value1 + ", json2 value = " + value2);
                }
            } else {
                // 如果json2不包含该键,则输出差异
                System.out.println("Key \"" + key + "\" found in json1 but not in json2, value = " + json1.get(key));
            }
        }

        // 获取json2的键集合,并检查json1中是否缺少这些键
        Iterator<String> keys2 = json2.keySet().iterator();
        while (keys2.hasNext()) {
            String key = keys2.next();
            // 如果json1不包含该键,则输出差异
            if (!json1.containsKey(key)) {
                System.out.println("Key \"" + key + "\" found in json2 but not in json1, value = " + json2.get(key));
            }
        }
    }
}

代码解释:

  • 定义JSON字符串: json1Str和json2Str是两个待比较的JSON字符串。

  • 解析JSON字符串: 使用JSON.parseObject方法将字符串解析为JSONObject对象。

  • 比较JSON对象:

  • 使用json1.keySet().iterator()获取json1的键集合,并遍历每个键。

  • 检查json2是否包含相同的键。

  • 如果两个键都存在,则比较它们的值。如果值不同,则输出差异。

  • 如果json2不包含该键,则输出json1中独有的键和值。

  • 使用json2.keySet().iterator()获取json2的键集合,并检查json1中是否缺少这些键。如果缺少,则输出差异。

注意事项:

示例代码仅比较了两个JSON对象的顶层字段。如果JSON对象包含嵌套对象或数组,需要编写更复杂的逻辑来递归地比较这些结构。

优化版本

  1. 减少重复查找: 在比较两个JSON对象时,避免对每个键进行多次查找。可以通过一次遍历收集所有需要的信息,然后再进行比较。
  2. 使用更高效的数据结构: 虽然JSONObject本身已经是一个基于HashMap的实现,但在处理大量数据时,任何可以减少查找和比较次数的优化都是有益的。
  3. 避免不必要的字符串操作: 在比较值时,如果可能的话,直接比较对象而不是将它们转换为字符串。
  4. 递归处理嵌套对象: 上面的代码没有处理嵌套对象或数组。为了完整比较两个JSON对象,我们需要添加递归逻辑。
  5. 使用Java 8的Stream API(可选): 虽然对于简单的键值对比较来说可能不是最直接的优化,但Stream API提供了强大的工具来处理集合,可能会在某些情况下提高代码的可读性和维护性。

下面是一个优化后的代码示例,它添加了递归处理嵌套对象和数组的逻辑:

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.util.Iterator;
import java.util.Map;

public class JsonDifference {

    public static void main(String[] args) {
        // 定义两个JSON对象
        String json1Str = "{\"name\":\"John\",\"age\":30,\"city\":\"New York\",\"address\":{\"street\":\"5th Avenue\",\"number\":100}}";
        String json2Str = "{\"name\":\"John\",\"age\":31,\"city\":\"Los Angeles\",\"address\":{\"street\":\"5th Avenue\",\"number\":101}}";

        // 将字符串解析为JSON对象
        JSONObject json1 = JSON.parseObject(json1Str);
        JSONObject json2 = JSON.parseObject(json2Str);

        // 调用方法比较两个JSON对象
        compareJsonObjects(json1, json2);
    }

    public static void compareJsonObjects(JSONObject json1, JSONObject json2) {
        compareMaps(json1.toJavaMap(), json2.toJavaMap(), "");
    }

    private static void compareMaps(Map<String, Object> map1, Map<String, Object> map2, String path) {
        Iterator<Map.Entry<String, Object>> iterator1 = map1.entrySet().iterator();
        while (iterator1.hasNext()) {
            Map.Entry<String, Object> entry1 = iterator1.next();
            String key = entry1.getKey();
            Object value1 = entry1.getValue();

            Object value2 = map2.get(key);

            if (value1 instanceof JSONObject && value2 instanceof JSONObject) {
                // 递归比较嵌套对象
                compareJsonObjects((JSONObject) value1, (JSONObject) value2);
            } else if (value1 instanceof JSONArray && value2 instanceof JSONArray) {
                // 递归比较嵌套数组(这里需要更复杂的逻辑来处理数组元素的不同)
                compareJsonArrays((JSONArray) value1, (JSONArray) value2, path + "." + key);
            } else {
                // 比较基本类型或字符串
                if (!areEqual(value1, value2)) {
                    System.out.println("Difference found at path \"" + path + "." + key + "\": " +
                            "value1 = " + value1 + ", value2 = " + value2);
                }
            }
        }

        // 检查map2中是否有map1中没有的键
        Iterator<Map.Entry<String, Object>> iterator2 = map2.entrySet().iterator();
        while (iterator2.hasNext()) {
            Map.Entry<String, Object> entry2 = iterator2.next();
            String key = entry2.getKey();
            if (!map1.containsKey(key)) {
                System.out.println("Key \"" + path + "." + key + "\" found in map2 but not in map1, value = " + entry2.getValue());
            }
        }
    }

    private static void compareJsonArrays(JSONArray array1, JSONArray array2, String path) {
        int length1 = array1.size();
        int length2 = array2.size();

        int minLength = Math.min(length1, length2);
        for (int i = 0; i < minLength; i++) {
            Object element1 = array1.get(i);
            Object element2 = array2.get(i);

            if (element1 instanceof JSONObject && element2 instanceof JSONObject) {
                // 递归比较嵌套对象
                compareJsonObjects((JSONObject) element1, (JSONObject) element2);
            } else if (element1 instanceof JSONArray && element2 instanceof JSONArray) {
                // 递归比较嵌套数组
                compareJsonArrays((JSONArray) element1, (JSONArray) element2, path + "[" + i + "]");
            } else {
                // 比较基本类型或字符串
                if (!areEqual(element1, element2)) {
                    System.out.println("Difference found at path \"" + path + "[" + i + "]\": " +
                            "value1 = " + element1 + ", value2 = " + element2);
                }
            }
        }

        // 检查数组长度是否不同
        if (length1 != length2) {
            System.out.println("Difference in array length at path \"" + path + "\": " +
                    "length1 = " + length1 + ", length2 = " + length2);
        }
    }

    private static boolean areEqual(Object obj1, Object obj2) {
        if (obj1 == null && obj2 == null) {
            return true;
        }
        if (obj1 == null || obj2 == null) {
            return false;
        }
        return obj1.equals(obj2);
    }
}

代码解释:

  1. 添加了 compareMaps 方法来比较两个Map对象(这里是从JSONObject转换来的),并递归地处理嵌套对象和数组。
  2. 添加了 compareJsonArrays 方法来比较两个JSONArray对象。

注意事项:

这个版本的数组比较是基于索引的,它假设两个数组在相同索引处的元素应该被比较(这可能不是所有情况下的正确行为,具体取决于你的需求)。此外,areEqual方法用于比较两个对象是否相等,处理了null值的情况。

总结


我是南国以南i记录点滴每天成长一点点,学习是永无止境的!转载请附原文链接!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南国以南i

你的鼓励将是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值