How to compare two JSON documents
Two JSON files can look completely different in a text diff while containing the same data, or look almost identical while hiding an important type change. A structural comparison avoids both problems.
Text diff versus structural diff
Tools such as git diff compare lines of text. That works well for source code, but JSON can be written in many textually different ways that mean the same thing:
{"name":"Ada","active":true}{
"active": true,
"name": "Ada"
}A text diff reports every line as changed, although the data is identical: only whitespace and key order differ. Object key order has no meaning in JSON, so a meaningful comparison should ignore it.
A structural diff parses both documents and walks through the data. It reports a difference only when a value was added, removed or changed. The JSON Diff tool works this way.
Reading the output
Each difference is reported with a path that starts at $, the root of the document:
~ $["active"]
before: true
after: false
+ $["age"]: 31
- $["nickname"]: "ada"~means the property exists in both documents with a different value.+means it exists only in the second document.-means it exists only in the first document.
Paths combine object keys and array indexes. $["orders"][0]["total"] is the total of the first element in the orders array. Following the path from left to right tells you exactly where to look.
Type changes matter
A structural diff also catches changes that are easy to overlook in text. The value 1 changing to "1", or false changing to "false", is reported because the type differs. These changes often break clients written in strictly typed languages, and they are a frequent cause of "the API looks the same but my app fails" problems.
The challenge with arrays
Unlike objects, arrays are ordered, so the diff compares them by position. That is correct for lists where order matters, such as steps in a workflow, but it produces noisy output when an element is inserted near the start:
before: ["admin", "editor", "viewer"]
after: ["owner", "admin", "editor", "viewer"]Every index now holds a different value, so the diff reports three changes and one addition, even though only "owner" was added.
When order does not matter in your data, normalise both documents before comparing:
- Sort arrays of simple values alphabetically.
- Sort arrays of objects by a stable key such as
idorsku. - Remove fields that are expected to differ, such as
updatedAt, request IDs or generated timestamps.
After normalising, the diff shows only meaningful changes.
Common uses
- API regressions. Save a known good response and compare it with the response from a new release.
- Configuration drift. Export settings from two environments and compare them to find a missing feature flag or a different timeout.
- Data migrations. Compare a sample of records before and after a migration script runs.
- Test snapshots. Review what changed in a snapshot file before accepting an update.
- Webhook debugging. Compare a payload that your handler processed correctly with one that failed.
Tips for reliable comparisons
- Make sure both inputs are valid JSON. The JSON formatter shows the exact syntax error if one does not parse.
- Compare like with like. Diffing a full response against a single nested object reports nearly everything as removed.
- Strip secrets and personal data before sharing diff output in tickets or chat.
- For very large documents, compare the relevant sub-object rather than the whole file so the output stays readable.