java 深度比较两个json并显示差异

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/41330715/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 05:49:06  来源:igfitidea点击:

Deep Comparing of two json and displaying the differences

javaarraysjson

提问by

I am trying to compare two dynamic json data and if they are not equal then i am printing the differences. For this i am using

我正在尝试比较两个动态 json 数据,如果它们不相等,那么我将打印差异。为此,我正在使用

Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
Map<String,Object> firstMap = g.fromJson(jsonElement1, mapType);
Map<String, Object> secondMap = g.fromJson(jsonElement2, mapType);
System.out.println(Maps.difference(firstMap, secondMap));

I need to display the difference in the console. This is the java code in which i am trying to display the differences of the json

我需要在控制台中显示差异。这是我试图显示 json 差异的 java 代码

      public class Tester {
public static ArrayList<Object> ls1 = new ArrayList<Object>();
 public static              ArrayList<Object> ls2 = new ArrayList<Object>();
            public static void main(String[] args) throws Exception {
                JsonParser parser = new JsonParser();

                try{
                    Gson g = new Gson();
                    JsonElement jsonElement1 = parser
                            .parse(new FileReader("D:\file1.json"));
                    JsonElement jsonElement2 = parser
                            .parse(new FileReader("D:\file2.json"));
                    System.out.println("Is the two JSON File Same: "+compareJson(jsonElement1, jsonElement2));
                    if(!compareJson(jsonElement1, jsonElement2)){
                        Type mapType = new TypeToken<Map<String, Object>>(){}.getType();
                        Map<String,Object> firstMap = g.fromJson(jsonElement1, mapType);
                        Map<String, Object> secondMap = g.fromJson(jsonElement2, mapType);
                        System.out.println(Maps.difference(firstMap, secondMap));
                    }
                    else{
                        System.out.println("The Two JSON Are SAME!!!!!!!!!!!!!!!");
                    }

                }catch(Exception e1){
                    e1.printStackTrace();
                }

            }

            public static boolean compareJson(JsonElement json1, JsonElement json2) {
                boolean isEqual = true;

                // Check whether both jsonElement are not null
                if (json1 != null && json2 != null) {

                    // Check whether both jsonElement are objects
                    if (json1.isJsonObject() && json2.isJsonObject()) {
                        Set<Entry<String, JsonElement>> ens1 = ((JsonObject) json1).entrySet();
                        Set<Entry<String, JsonElement>> ens2 = ((JsonObject) json2).entrySet();
                        JsonObject json2obj = (JsonObject) json2;
                        if (ens1 != null && ens2 != null && (ens2.size() == ens1.size())) {
                            // Iterate JSON Elements with Key values
                            for (Entry<String, JsonElement> en : ens1) {
                                isEqual = isEqual && compareJson(en.getValue(),json2obj.get(en.getKey()));
                            }
                        } else {
                            return false;
                        }
                    }
                    // Check whether both jsonElement are arrays
                    else if (json1.isJsonArray() && json2.isJsonArray()) {
                        JsonArray jarr1 = json1.getAsJsonArray();
                        JsonArray jarr2 = json2.getAsJsonArray();
                        if (jarr1.size() != jarr2.size()) {
                            return false;
                        } else {
                            int i = 0;
                            // Iterate JSON Array to JSON Elements
                            for (JsonElement je : jarr1) {
                                isEqual = isEqual && compareJson(je, jarr2.get(i));
                                i++;
                            }
                            if (isEqual) {
                                Object[] o1 = ls1.toArray();
                                Object[] o2 = ls2.toArray();
                                isEqual = Arrays.deepEquals(o1, o2);
                            }
                        }

                    }

                    // Check whether both jsonElement are null
                    else if (json1.isJsonNull() && json2.isJsonNull()) {
                        return true;
                    }

                    // Check whether both jsonElement are primitives
                    else if (json1.isJsonPrimitive() && json2.isJsonPrimitive()) {
                        ls1.add(json1);
                        ls2.add(json2);         
                    }               
                } else if (json1 == null && json2 == null) {
                    return true;
                } else {
                    return false;
                }
                return isEqual;
            }
        }

the object array

对象数组

if (isEqual) {
                            Object[] o1 = ls1.toArray();
                            Object[] o2 = ls2.toArray();
                            isEqual = Arrays.deepEquals(o1, o2);
                        }

the object array o1 and o2 are null dont know why it is null. These are the two sample json i am using for testing json1 {"Company List":["Compnay: Paypal","Compnay: eBay","Compnay: Google"]}json2 {"Company List":["Compnay: Viswesh","Compnay: Anand","Compnay: Anand"]}in both the json the value for company is different so the code has to return false but the code return true

对象数组 o1 和 o2 为空,不知道为什么它为空。这些是我用来测试 json1 {"Company List":["Compnay: Paypal","Compnay: eBay","Compnay: Google"]}json2的两个示例 json{"Company List":["Compnay: Viswesh","Compnay: Anand","Compnay: Anand"]}公司的值不同,因此代码必须返回 false 但代码返回 true

回答by Mark

The comment section was getting too long, so here's an answer instead:

评论部分太长了,所以这里有一个答案:

First off, you still have a problem if your Json Objects have different structures. For example:

首先,如果您的 Json 对象具有不同的结构,您仍然会遇到问题。例如:

{"Company List":["Compnay: eBay","Compnay: Google","Compnay: Paypal"]} 

{"Company List":"ImAString"}

Neither is null, it's a primitive and an array. You don't catch that case, so your isEqual will remain true.

两者都不是 null,它是一个原始类型和一个数组。您没有发现这种情况,因此您的 isEqual 将保持为真。



Anyway, back to the problem at hand.

无论如何,回到手头的问题。

Arrays should not have to be ordered the same to be equal in your case.

在您的情况下,数组不应该被排序为相同。

if (isEqual) {
    Object[] o1 = ls1.toArray();
    Object[] o2 = ls2.toArray();
    isEqual = Arrays.deepEquals(o1, o2);
}

You should be able to easily solve it by changing this into this:

您应该可以通过将其更改为以下内容来轻松解决它:

if (isEqual) {
    isEqual = ls1.containsAll(ls2);
}

Although I should mention that I find it really odd that your ls1 and ls2 are both static and just keep getting entries. In your examples it doesn't matter because they are so small, but on big files, you will get huge ArrayLists with lots of values appearing multiple times.

尽管我应该提一下,我发现您的 ls1 和 ls2 都是静态的并且只是不断获取条目,这真的很奇怪。在您的示例中,这并不重要,因为它们太小了,但是在大文件中,您将获得巨大的 ArrayList,其中包含多次出现的大量值。

And comparing them all every time you get to a JsonArray seems like it would be a huge waste of time.

每次到达 JsonArray 时都比较它们似乎会浪费大量时间。



Since this still has the problem of not being able to compare differently ordered JSON Arrays with JSON Elements that aren't primitives, here's the brute force approach to comparing two arrays. Keep in mind that it's far from being an optimal approach, but it IS relatively easy to implement:

由于这仍然存在无法将不同顺序的 JSON 数组与不是基元的 JSON 元素进行比较的问题,这里是比较两个数组的蛮力方法。请记住,这远非最佳方法,但实施起来相对容易:

public static boolean equality(ArrayList<Object> list1, ArrayList<Object> list2) {  
    if (list1.length != list2.length) return false;

    for (Object entry1 : list1) {
        Object equalEntry = null;

        for(Object entry2 : list2) { 
            if (entry1.equals(entry2)) {
                equalEntry = entry2;
                break;
            }
        } 

        if (equalEntry == null) return false;       
        list2.remove(equalEntry);
    } 

    return true;
}

I should also mention that it's obviously not as simple as if (entry1.equals(entry2)). You will probably have to do the recursion at this point and call your compare method. Also I'm pretty sure your Lists hold JSON Elements and not Objects ;)

我还应该提到,它显然不像if (entry1.equals(entry2)). 此时您可能必须进行递归并调用您的比较方法。此外,我很确定您的列表包含 JSON 元素而不是对象;)