Best way to compare two JSON files in Java
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 sh开发者_如何学运维ould be handled?
I recommend the zjsonpatch library, which presents the diff information in accordance with RFC 6902 (JSON Patch). You can use it with Jackson:
JsonNode beforeNode = jacksonObjectMapper.readTree(beforeJsonString);
JsonNode afterNode = jacksonObjectMapper.readTree(afterJsonString);
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).
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
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);
}
...
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.
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.
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 }
}
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;
}
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.
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));
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"
}
]
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
精彩评论