44

How would you suggest this task is approached?

The challenge as i see it is in presenting diff information intelligently. Before i go reinventing the wheel, is there an accepted approach of how such a comparison should be handled?

malana
  • 5,045
  • 3
  • 28
  • 41
James Raitsev
  • 92,517
  • 154
  • 335
  • 470

11 Answers11

33

I recommend the zjsonpatch library, which presents the diff information in accordance with RFC 6902 (JSON Patch). You can use it with Jackson:

import com.fasterxml.jackson.databind.{ObjectMapper, JsonNode}
JsonNode beforeNode = jacksonObjectMapper.readTree(beforeJsonString);
JsonNode afterNode = jacksonObjectMapper.readTree(afterJsonString);

import com.flipkart.zjsonpatch.JsonDiff
JsonNode patch = JsonDiff.asJson(beforeNode, afterNode);
String diffs = patch.toString();

This library is better than fge-json-patch (which was mentioned in another answer) because it can detect items being inserted/removed from arrays. Fge-json-patch cannot handle that (if an item is inserted into the middle of an array, it will think that item and every item after that was changed since they are all shifted over by one).

Richard Gomes
  • 5,675
  • 2
  • 44
  • 50
pacoverflow
  • 3,726
  • 11
  • 41
  • 71
  • 1
    This only compares the structure of the json documents. – Ean V Oct 04 '16 at 23:32
  • 2
    Its comparing both keys and values. How to make it only for keys ? – Saagar May 27 '19 at 13:14
  • The code didn't work for me. You probably need to make a new `ObjectMapper` first: ```java ObjectMapper mapper = new ObjectMapper(); JsonNode beforeNode = jacksonObjectMapper.readTree(beforeJsonString); JsonNode afterNode = jacksonObjectMapper.readTree(afterJsonString); JsonNode patch = JsonDiff.asJson(beforeNode, afterNode); String diffs = patch.toString(); ``` – kohane15 Oct 28 '20 at 08:42
15

I've done good experience with JSONAssert.

import org.junit.Test;
import org.apache.commons.io.FileUtils;
import org.skyscreamer.jsonassert.JSONAssert;
import org.skyscreamer.jsonassert.JSONCompareMode;

... 
@Test
public void myTest() {
  String expectedJson = FileUtils.readFileToString("/expectedFile");
  String actualJson = FileUtils.readFileToString("/actualFile");
  JSONAssert.assertEquals(expectedJson, actualJson, JSONCompareMode.STRICT);
}
... 
Cengiz
  • 5,375
  • 6
  • 52
  • 77
15

The easiest way to compare json strings is using JSONCompare from JSONAssert library. The advantage is, it's not limited to structure only and can compare values if you wish:

JSONCompareResult result = 
     JSONCompare.compareJSON(json1, json2, JSONCompareMode.STRICT);
System.out.println(result.toString());

which will output something like:

Expected: VALUE1
     got: VALUE2
 ; field1.field2
Ean V
  • 5,091
  • 5
  • 31
  • 39
  • i am getting compile time error as: The type org.json.JSONArray cannot be resolved. It is indirectly referenced from required .class files – Vikas Suryawanshi Feb 07 '18 at 06:39
  • 1
    A general rule, if u wanna use a lib, include all its dependencies or use maven to get the dependencies automatically. – Ean V Mar 28 '18 at 04:42
  • This did not work as advertised and when I emailed them, the email address was no longer valid. Abandonware?? – likejudo May 27 '20 at 16:20
  • see https://stackoverflow.com/questions/62048635/finding-json-diff-fails-using-jsonassert – likejudo May 27 '20 at 17:09
12

This only addresses equality, not differences.


With Jackson.

ObjectMapper mapper = new ObjectMapper();

JsonNode tree1 = mapper.readTree(jsonInput1);
JsonNode tree2 = mapper.readTree(jsonInput2);

boolean areTheyEqual = tree1.equals(tree2);

From the JavaDoc for JsonNode.equals:

Equality for node objects is defined as full (deep) value equality. This means that it is possible to compare complete JSON trees for equality by comparing equality of root nodes.

Luis
  • 3,451
  • 1
  • 27
  • 41
Programmer Bruce
  • 64,977
  • 7
  • 99
  • 97
5

You could try the XStream's architecture, handling of JSON mappings

Also, take a look at this post: Comparing two XML files & generating a third with XMLDiff in C#. It's in C# but the logic is the same.

Community
  • 1
  • 1
Jean-François Beaulieu
  • 4,305
  • 22
  • 74
  • 107
4

I had a similar problem and ended up writing my own library:

https://github.com/algesten/jsondiff

It does both diffing/patching.

Diffs are JSON-objects themselves and have a simple syntax for object merge/replace and array insert/replace.

Example:

original
{
   a: { b: 42 }
}

patch
{
  "~a": { c: 43 }
}

The ~ indicates an object merge.

result
{
   a: { b: 42, c: 43 }
}
Mithun Satheesh
  • 27,240
  • 14
  • 77
  • 101
Martin Algesten
  • 13,052
  • 4
  • 54
  • 77
2

You can use below dependancy to compare Json with STRICT,LENIENT,IGNORE_ORDER etc.

<dependency>
    <groupId>org.skyscreamer</groupId>
    <artifactId>jsonassert</artifactId>
    <version>1.5.0</version>
    <scope>test</scope>
</dependency>
  public static boolean isTwoJsonEquals(JSONObject firstObj,JSONObject secondObj, JSONCompareMode compareMode){
    try {
      JSONCompareResult result = JSONCompare.compareJSON(firstObj, secondObj, compareMode);

      return result.passed();
    } catch (JSONException e) {
      e.printStackTrace();
    }
    return false;
  }
Afsar Ali
  • 555
  • 6
  • 17
1

For people who are already using Jackson, I recommend json-patch

final JsonNode patchNode = JsonDiff.asJson(firstNode, secondNode);
System.out.println("Diff=" + m.writeValueAsString(patchNode));
Didac Montero
  • 2,046
  • 19
  • 27
  • 1
    I went to their site and find it is licensed under LGPLv3. correct me if I am mistaken but isn't LGPL very restrictive for corporations to use? – likejudo May 27 '20 at 17:08
1

json-lib

What I would do is parse the json data using json-lib. This will result in regular java objects which you can compare using the equals methods. This is only valid though assuming the guys from json-lib properly implemented the equals method, but that you can easily test.

W. Goeman
  • 1,674
  • 2
  • 15
  • 31
0

In case if want to compare two JSON Ignoring the order of elements/object, see if this library helps you.

Usage:

List<Diff> diff = new DnjsonDiff().getDiff(String left, String right)
Left =[{"name":"Bob","businessKey":"4444"},{"name":"John","businessKey":"5555"}]
Right = [{"name":"Bob","businessKey":"6666"},{"name":"John", "businessKey":"4444"}]

Diff:

[
    {
        "op": "replace",
        "configuredValue": "John",
        "intendedValue": "Bob",
        "businessKey": "4444"
    },
    {
        "op": "remove",
        "configuredValue": null,
        "intendedValue": "{\"name\":\"John\",\"businessKey\":\"5555\"}",
        "businessKey": "5555"
    },
    {
        "op": "add",
        "configuredValue": "{\"name\":\"Bob\",\"businessKey\":\"6666\"}",
        "intendedValue": null,
        "businessKey": "null"
    }
]
David Buck
  • 3,752
  • 35
  • 31
  • 35
Naresh
  • 25
  • 5
0

Using Google's Guava library for comparison. Check this answer which has detailed explanation on how to use this.

https://stackoverflow.com/a/50969020/17762303

KRISH C
  • 21
  • 4