2

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

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

      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

  • You probably want to tag Java as well. What do you mean does not work in the first example? what is the input, output, and expected output? – kabanus Dec 26 '16 at 11:46
  • if the json is of object type then i am able to get the difference –  Dec 26 '16 at 11:48
  • added the java code as well. could anyone help me with this. Also i dont know if my code is an optimized one –  Dec 26 '16 at 11:58
  • So... wait... the second code snippet is where exactly? Outside of your compare method? – Mark Dec 27 '16 at 10:53
  • @Mark it is inside the compare method only. when i execute the above code in debug the object array is null –  Dec 27 '16 at 10:54
  • @axelH i need to do a deep compare of the two json what i have posted is sample one and the real json is very huge –  Dec 27 '16 at 11:04
  • 1
    Possible duplicate of [Compare two JSON objects in Java](http://stackoverflow.com/questions/2253750/compare-two-json-objects-in-java) – Dherik Dec 27 '16 at 11:04
  • @Dherik see i am able to compare the jsons but could not print the all the differences if the two json are not equal –  Dec 27 '16 at 11:12
  • @Calvin, I think `JSONAssert` can show only the differences. Try the `JSONCompare` (http://jsonassert.skyscreamer.org/apidocs/index.html) available in `JSONAssert `. – Dherik Dec 27 '16 at 11:21
  • @Mark any idea on the reason why the array returned as null –  Dec 27 '16 at 11:40
  • Actually, no :(. I tried creating an empty ArrayList and calling the toArray() method, it doesn't return null, just makes the resulting array empty. Of course if your ArrayList was null, you'd get a NullPointerException, but it doesn't seem like that's your problem. Did you debug it? Are you sure the .toArray() method returned null instead of an array? – Mark Dec 27 '16 at 11:58
  • @Mark i have edited the code now the arraylist is not empty, but when comparing two json with same key but with different value it return as true instead of returning as false –  Dec 28 '16 at 03:23
  • @Calvin Which json library are you using? I'd like to test the code myself, but a different library might screw up the results – Mark Dec 28 '16 at 08:25
  • @Mark i am using Gson. These are the imports that i did import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.reflect.TypeToken; –  Dec 28 '16 at 08:28
  • @Mark i need to do something like this if the json values are same irrespective of their order then it should not do anything. if the json are not same then i need to print the differences –  Dec 28 '16 at 08:30
  • @Calvin So... here's the thing... if I try your code with your example, this is my output: `Is the two JSON File Same: false` `not equal: value differences={Company List=([Compnay: Paypal, Compnay: eBay, Compnay: Google], [Compnay: Viswesh, Compnay: Anand, Compnay: Anand])}` – Mark Dec 28 '16 at 08:41
  • @Mark if you try this on json1: {"Company List":["Compnay: eBay","Compnay: Google","Compnay: Paypal"]} and json2: {"Company List":["Compnay: Paypal","Compnay: eBay","Compnay: Google"]} in these two json the values are same but the order is different my code returns not equal but i need to get the result as they are equal –  Dec 28 '16 at 08:49
  • @Mark my thing is my code should return as two json are same if the order of the json is different but the values are same –  Dec 28 '16 at 08:51
  • @Mark just like you had posted these two json are also returning that they are same {"Company List":["Compnay: eBay","Compnay: Google","Compnay: Paypal"]} {"Company List":"ImAString"} –  Dec 28 '16 at 09:11
  • @Mark it feels very bad as i had spent lots of time to fix this simple issue –  Dec 28 '16 at 09:11

1 Answers1

0

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:

{"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.


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.

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


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:

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 ;)

Mark
  • 1,498
  • 1
  • 9
  • 13
  • Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/131699/discussion-on-answer-by-mark-deep-comparing-of-two-json-and-displaying-the-diffe). – Bhargav Rao Dec 28 '16 at 12:08
  • let me make surethat my understanding of your thoughts is correct. You want me to say that if the json has an array/list and the order is different or the value are not equal then i say that the json are not equal and then use the ma to print the differences. is it right? –  Dec 28 '16 at 12:09
  • @Mark is this the way you had mentioned –  Dec 29 '16 at 07:17