🌐
GitHub
github.com › deblockt › json-diff
GitHub - deblockt/json-diff: A library to generate a json diff on java · GitHub
A library to generate a json diff on java. Contribute to deblockt/json-diff development by creating an account on GitHub.
Starred by 54 users
Forked by 10 users
Languages   Java
🌐
GitHub
github.com › fslev › json-compare
GitHub - fslev/json-compare: A Java library for comparing JSONs · GitHub
A Java library for matching JSONs, with some tweaks ! Compare any JSON convertible Java objects and check the differences between them when matching fails.
Starred by 75 users
Forked by 14 users
Languages   Java
🌐
GitHub
github.com › dann41 › jsoncomparator
GitHub - dann41/jsoncomparator: Java library to compare JSON objects
Java library to compare JSON objects. Contribute to dann41/jsoncomparator development by creating an account on GitHub.
Author   dann41
🌐
GitHub
github.com › java-json-tools › json-patch › blob › master › src › main › java › com › github › fge › jsonpatch › diff › JsonDiff.java
json-patch/src/main/java/com/github/fge/jsonpatch/diff/JsonDiff.java at master · java-json-tools/json-patch
import java.util.*; · /** * JSON "diff" implementation · * * <p>This class generates a JSON Patch (as in, an RFC 6902 JSON Patch) given · * two JSON values as inputs. The patch can be obtained directly as a {@link · * JsonPatch} or as a {@link JsonNode}.</p> * * <p>Note: there is <b>no guarantee</b> about the usability of the generated ·
Author   java-json-tools
🌐
GitHub
github.com › flipkart-incubator › zjsonpatch
GitHub - flipkart-incubator/zjsonpatch: This is an implementation of RFC 6902 JSON Patch written in Java
Given a patch, it apply it to source JSON and return a target JSON which can be ( JSON object or array or value ). This operation performed on a clone of source JSON ( thus, the source JSON is unmodified and can be used further).
Starred by 566 users
Forked by 156 users
Languages   Java 100.0% | Java 100.0%
🌐
GitHub
github.com › topics › json-diff
json-diff · GitHub Topics · GitHub
javascript json angular component comparison json-diff comparison-tool json-compare json-diff-checker angular-json-difference json-difference ... JSON Diff and Patch using Myer's Algorithm, for EditorJS. Using JSON RFC Format ... Jacksync provides a library for synchronization by producing and applying a JSON Patches to Java objects.
🌐
GitHub
github.com › kvnxiao › jsonequals
GitHub - kvnxiao/jsonequals: A flexible JSON deep-equality comparator with optional ignoring of JSON keys and values
The current version of JsonEquals ... by indicating differences in response data. ... JsonEquals uses LazyJSON, a simple and lightweight Java library to parse (read) JSON....
Starred by 13 users
Forked by 7 users
Languages   Java 100.0% | Java 100.0%
🌐
GitHub
github.com › gnieh › diffson
GitHub - gnieh/diffson: A scala diff/patch library for Json
A scala diff/patch library for Json. Contribute to gnieh/diffson development by creating an account on GitHub.
Starred by 322 users
Forked by 52 users
Languages   Scala 100.0% | Scala 100.0%
Find elsewhere
Top answer
1 of 4
102

Reading the JSON documents as Maps and comparing them

You could read both JSON documents as Map<K, V>. See the below examples for Jackson and Gson:

ObjectMapper mapper = new ObjectMapper();
TypeReference<HashMap<String, Object>> type = 
    new TypeReference<HashMap<String, Object>>() {};

Map<String, Object> leftMap = mapper.readValue(leftJson, type);
Map<String, Object> rightMap = mapper.readValue(rightJson, type);
Gson gson = new Gson();
Type type = new TypeToken<Map<String, Object>>(){}.getType();

Map<String, Object> leftMap = gson.fromJson(leftJson, type);
Map<String, Object> rightMap = gson.fromJson(rightJson, type);

Then use Guava's Maps.difference(Map<K, V>, Map<K, V>) to compare them. It returns a MapDifference<K, V> instance:

MapDifference<String, Object> difference = Maps.difference(leftMap, rightMap);

If you are not happy with the result, you can consider flattening the maps and then compare them. It will provide better comparison results especially for nested objects and arrays.

Creating flat Maps for the comparison

To flat the map, you can use:

public final class FlatMapUtil {

    private FlatMapUtil() {
        throw new AssertionError("No instances for you!");
    }

    public static Map<String, Object> flatten(Map<String, Object> map) {
        return map.entrySet().stream()
                .flatMap(FlatMapUtil::flatten)
                .collect(LinkedHashMap::new, (m, e) -> m.put("/" + e.getKey(), e.getValue()), LinkedHashMap::putAll);
    }

    private static Stream<Map.Entry<String, Object>> flatten(Map.Entry<String, Object> entry) {

        if (entry == null) {
            return Stream.empty();
        }

        if (entry.getValue() instanceof Map<?, ?>) {
            return ((Map<?, ?>) entry.getValue()).entrySet().stream()
                    .flatMap(e -> flatten(new AbstractMap.SimpleEntry<>(entry.getKey() + "/" + e.getKey(), e.getValue())));
        }

        if (entry.getValue() instanceof List<?>) {
            List<?> list = (List<?>) entry.getValue();
            return IntStream.range(0, list.size())
                    .mapToObj(i -> new AbstractMap.SimpleEntry<String, Object>(entry.getKey() + "/" + i, list.get(i)))
                    .flatMap(FlatMapUtil::flatten);
        }

        return Stream.of(entry);
    }
}

It uses the JSON Pointer notation defined in the RFC 6901 for the keys, so you can easily locate the values.

Example

Consider the following JSON documents:

{
  "name": {
    "first": "John",
    "last": "Doe"
  },
  "address": null,
  "birthday": "1980-01-01",
  "company": "Acme",
  "occupation": "Software engineer",
  "phones": [
    {
      "number": "000000000",
      "type": "home"
    },
    {
      "number": "999999999",
      "type": "mobile"
    }
  ]
}
{
  "name": {
    "first": "Jane",
    "last": "Doe",
    "nickname": "Jenny"
  },
  "birthday": "1990-01-01",
  "occupation": null,
  "phones": [
    {
      "number": "111111111",
      "type": "mobile"
    }
  ],
  "favorite": true,
  "groups": [
    "close-friends",
    "gym"
  ]
}

And the following code to compare them and show the differences:

Map<String, Object> leftFlatMap = FlatMapUtil.flatten(leftMap);
Map<String, Object> rightFlatMap = FlatMapUtil.flatten(rightMap);

MapDifference<String, Object> difference = Maps.difference(leftFlatMap, rightFlatMap);

System.out.println("Entries only on the left\n--------------------------");
difference.entriesOnlyOnLeft()
          .forEach((key, value) -> System.out.println(key + ": " + value));

System.out.println("\n\nEntries only on the right\n--------------------------");
difference.entriesOnlyOnRight()
          .forEach((key, value) -> System.out.println(key + ": " + value));

System.out.println("\n\nEntries differing\n--------------------------");
difference.entriesDiffering()
          .forEach((key, value) -> System.out.println(key + ": " + value));

It will produce the following output:

Entries only on the left
--------------------------
/address: null
/phones/1/number: 999999999
/phones/1/type: mobile
/company: Acme


Entries only on the right
--------------------------
/name/nickname: Jenny
/groups/0: close-friends
/groups/1: gym
/favorite: true


Entries differing
--------------------------
/birthday: (1980-01-01, 1990-01-01)
/occupation: (Software engineer, null)
/name/first: (John, Jane)
/phones/0/number: (000000000, 111111111)
/phones/0/type: (home, mobile)
2 of 4
54

Creating a JSON Patch document

Alternatively to the approach described in the other answer, you could use the Java API for JSON Processing defined in the JSR 374 (it doesn't use on Gson or Jackson). The following dependencies are required:

<!-- Java API for JSON Processing (API) -->
<dependency>
    <groupId>javax.json</groupId>
    <artifactId>javax.json-api</artifactId>
    <version>1.1.2</version>
</dependency>

<!-- Java API for JSON Processing (implementation) -->
<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.json</artifactId>
    <version>1.1.2</version>
</dependency>

Then you can create a JSON diff from the JSON documents. It will produce a JSON Patch document as defined in the RFC 6902:

JsonPatch diff = Json.createDiff(source, target);

When applied to the source document, the JSON Patch yields the target document. The JSON Patch can be applied to the source document using:

JsonObject patched = diff.apply(source);

Creating a JSON Merge Patch document

Depending on your needs, you could create a JSON Merge Patch document as defined in the RFC 7396:

JsonMergePatch mergeDiff = Json.createMergeDiff(source, target);

When applied to the source document, the JSON Merge Patch yields the target document. To patch the source, use:

JsonValue patched = mergeDiff.apply(source);

Pretty printing JSON documents

To pretty print the JSON documents, you can use:

System.out.println(format(diff.toJsonArray()));
System.out.println(format(mergeDiff.toJsonValue()));
public static String format(JsonValue json) {
    StringWriter stringWriter = new StringWriter();
    prettyPrint(json, stringWriter);
    return stringWriter.toString();
}

public static void prettyPrint(JsonValue json, Writer writer) {
    Map<String, Object> config =
            Collections.singletonMap(JsonGenerator.PRETTY_PRINTING, true);
    JsonWriterFactory writerFactory = Json.createWriterFactory(config);
    try (JsonWriter jsonWriter = writerFactory.createWriter(writer)) {
        jsonWriter.write(json);
    }
}

Example

Consider the following JSON documents:

{
  "name": {
    "first": "John",
    "last": "Doe"
  },
  "address": null,
  "birthday": "1980-01-01",
  "company": "Acme",
  "occupation": "Software engineer",
  "phones": [
    {
      "number": "000000000",
      "type": "home"
    },
    {
      "number": "999999999",
      "type": "mobile"
    }
  ]
}
{
  "name": {
    "first": "Jane",
    "last": "Doe",
    "nickname": "Jenny"
  },
  "birthday": "1990-01-01",
  "occupation": null,
  "phones": [
    {
      "number": "111111111",
      "type": "mobile"
    }
  ],
  "favorite": true,
  "groups": [
    "close-friends",
    "gym"
  ]
}

And the following code to produce a JSON Patch:

JsonValue source = Json.createReader(new StringReader(leftJson)).readValue();
JsonValue target = Json.createReader(new StringReader(rightJson)).readValue();

JsonPatch diff = Json.createDiff(source.asJsonObject(), target.asJsonObject());
System.out.println(format(diff.toJsonArray()));

It will produce the following output:

[
    {
        "op": "replace",
        "path": "/name/first",
        "value": "Jane"
    },
    {
        "op": "add",
        "path": "/name/nickname",
        "value": "Jenny"
    },
    {
        "op": "remove",
        "path": "/address"
    },
    {
        "op": "replace",
        "path": "/birthday",
        "value": "1990-01-01"
    },
    {
        "op": "remove",
        "path": "/company"
    },
    {
        "op": "replace",
        "path": "/occupation",
        "value": null
    },
    {
        "op": "replace",
        "path": "/phones/1/number",
        "value": "111111111"
    },
    {
        "op": "remove",
        "path": "/phones/0"
    },
    {
        "op": "add",
        "path": "/favorite",
        "value": true
    },
    {
        "op": "add",
        "path": "/groups",
        "value": [
            "close-friends",
            "gym"
        ]
    }
]

Now consider the following code to produce a JSON Merge Patch:

JsonValue source = Json.createReader(new StringReader(leftJson)).readValue();
JsonValue target = Json.createReader(new StringReader(rightJson)).readValue();

JsonMergePatch mergeDiff = Json.createMergeDiff(source, target);
System.out.println(format(mergeDiff.toJsonValue()));

It will produce the following output:

{
    "name": {
        "first": "Jane",
        "nickname": "Jenny"
    },
    "address": null,
    "birthday": "1990-01-01",
    "company": null,
    "occupation": null,
    "phones": [
        {
            "number": "111111111",
            "type": "mobile"
        }
    ],
    "favorite": true,
    "groups": [
        "close-friends",
        "gym"
    ]
}

Different results when applying the patches

When the patch document is applied, the results are slightly different for the approaches described above. Consider the following code that applies JSON Patch to a document:

JsonPatch diff = ...
JsonValue patched = diff.apply(source.asJsonObject());
System.out.println(format(patched));

It produces:

{
    "name": {
        "first": "Jane",
        "last": "Doe",
        "nickname": "Jenny"
    },
    "birthday": "1990-01-01",
    "occupation": null,
    "phones": [
        {
            "number": "111111111",
            "type": "mobile"
        }
    ],
    "favorite": true,
    "groups": [
        "close-friends",
        "gym"
    ]
}

Now consider the following code that applies JSON Merge Patch to a document:

JsonMergePatch mergeDiff = ...
JsonValue patched = mergeDiff.apply(source);
System.out.println(format(patched));

It produces:

{
    "name": {
        "first": "Jane",
        "last": "Doe",
        "nickname": "Jenny"
    },
    "birthday": "1990-01-01",
    "phones": [
        {
            "number": "111111111",
            "type": "mobile"
        }
    ],
    "favorite": true,
    "groups": [
        "close-friends",
        "gym"
    ]
}

In the first example, the occupation property is null. In the second example, it's omitted. It's due to the null semantics on JSON Merge Patch. From the RFC 7396:

If the target does contain the member, the value is replaced. Null values in the merge patch are given special meaning to indicate the removal of existing values in the target. [...]

This design means that merge patch documents are suitable for describing modifications to JSON documents that primarily use objects for their structure and do not make use of explicit null values. The merge patch format is not appropriate for all JSON syntaxes.

🌐
GitHub
github.com › nsf › jsondiff
GitHub - nsf/jsondiff: JsonDiff library
The main purpose of the library is integration into tests which use json and providing human-readable output of test results. The lib can compare two json items and return a detailed report of the comparison. At the moment it can detect a couple of types of differences:
Starred by 227 users
Forked by 49 users
Languages   Go 100.0% | Go 100.0%
🌐
Libraries.io
libraries.io › maven › io.github.deblockt:json-diff
io.github.deblockt:json-diff 2.1.0 on Maven - Libraries.io - security & maintenance data for open source software
March 17, 2021 - The goal of this library is to provide a readable diff between two json file. In addition to the differential, a similarity score is calculated. This score can be used to compare several json with each other and find the two most similar.
🌐
Baeldung
baeldung.com › home › json › jackson › compare two json objects with jackson
Compare Two JSON Objects with Jackson | Baeldung
January 8, 2024 - Learn how to use Jackson to compare two JSON objects using the built-in comparator and a custom comparator
🌐
GitHub
github.com › andreyvit › json-diff
GitHub - andreyvit/json-diff: Structural diff for JSON files · GitHub
% json-diff --help Usage: json-diff [-vCjfonskKp] first.json second.json Arguments: <first.json> Old file <second.json> New file General options: -v, --verbose Output progress info -C, --[no-]color Colored output -j, --raw-json Display raw JSON encoding of the diff -f, --full Include the equal sections of the document, not just the deltas --max-elisions COUNT Max number of ...s to show in a row in "deltas" mode (before collapsing them) -o, --output-keys KEYS Always print this comma separated keys, with their value, if they are part of an object with any diff -x, --exclude-keys KEYS Exclude these comma separated keys from comparison on both files -n, --output-new-only Output only the updated and new key/value pairs (without marking them as such).
Starred by 1.2K users
Forked by 138 users
Languages   CoffeeScript 66.6% | JavaScript 33.4%
🌐
JSON Diff
jsondiff.com
JSON Diff - The semantic JSON compare tool
Validate, format, and compare two JSON documents. See the differences between the objects instead of just the new lines and mixed up properties.
🌐
Stanislav Myachenkov
smyachenkov.com › posts › how to compare json documents in java
How To Compare JSON Documents In Java | Stanislav Myachenkov
June 9, 2020 - There are libraries for JSON Patch for many languages, with zjsonpatch being the most popular solution for Java. Those libraries calculate the differences between two objects.
🌐
GitHub
github.com › marketplace › actions › jd-json-diff-and-patch
jd - JSON diff and patch - GitHub Marketplace
Usage: jd [OPTION]... FILE1 [FILE2] Diff and patch JSON files. Prints the diff of FILE1 and FILE2 to STDOUT. When FILE2 is omitted the second input is read from STDIN. When patching (-p) FILE1 is a diff. Options: -color Print color diff. -p Apply patch FILE1 to FILE2 or STDIN.