【问题标题】:Deep Comparing of two json and displaying the differences深度比较两个json并显示差异
【发布时间】:2017-05-10 21:17:34
【问题描述】:

我正在尝试比较两个动态 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));

我需要在控制台中显示差异。 这是我试图显示 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;
            }
        }

对象数组

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

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

【问题讨论】:

  • 您可能还想标记 Java。你的意思是在第一个例子中不起作用?输入、输出和预期输出是什么?
  • 如果 json 是对象类型,那么我能够得到差异
  • 也添加了java代码。谁能帮我解决这个问题。我也不知道我的代码是不是优化的
  • 所以……等等……第二个代码 sn-p 到底在哪里?在您的比较方法之外?

标签: java arrays json


【解决方案1】:

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

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

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

{"Company List":"ImAString"}

两者都不是 null,它是一个原始数组和一个数组。你没有抓住这种情况,所以你的 isEqual 将保持真实。


不管怎样,回到手头的问题。

在您的情况下,数组的顺序不必相同。

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

您应该可以通过将其更改为以下方式轻松解决它:

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

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

每次你得到一个 JsonArray 时都比较它们似乎会浪费大量时间。


由于这仍然存在无法将不同顺序的 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;
}

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

【讨论】:

  • 评论不用于扩展讨论;这个对话是moved to chat
  • 请确认我对您的想法的理解是正确的。你想让我说,如果 json 有一个数组/列表并且顺序不同或值不相等,那么我说 json 不相等,然后使用 ma 打印差异。对吗?
  • @Mark 是你提到的方式
猜你喜欢
  • 2015-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-06
  • 1970-01-01
相关资源
最近更新 更多