Compare two JSON documents
A line-by-line text diff of two JSON files is noisy: reformatting or reordering keys lights up the whole file even when nothing really changed. This tool does a structural comparison instead — it parses both documents and compares the data, so you see only the values that actually differ, each labelled by its path.
How it works
The tool parses the left (original) and right (changed) documents, then walks the two trees in parallel:
- Objects are matched by key, regardless of order.
- Arrays are matched by index (position).
- Every leaf is classified as added (only on the right), removed (only on the left) or changed (present on both with different values).
Each difference is reported with its dotted path, such as limits.upload or
tags[1]. Added values are shown in green with a plus, removed values in red
with a minus.
Example
Comparing these two documents:
{ "name": "api", "limits": { "upload": 5 }, "tags": ["a", "b"] }
{ "name": "api", "limits": { "upload": 20 }, "tags": ["a", "c"] }
reports two changes and nothing else:
~ limits.upload: 5 → 20
~ tags[1]: "b" → "c"
name is identical, so it is not listed. Everything runs in your browser, so
nothing is uploaded.
When structural diff beats text diff
Text diff tools (git diff, Unix diff) compare lines. They are excellent for code but poor for JSON, because:
- Pretty-printing a minified file, or minifying a pretty-printed one, shows every line as changed even though no data changed.
- Reordering keys in an object (which is semantically meaningless) shows up as both removed and added lines.
- Moving an array element ripples changes across many subsequent lines if the array is short.
Structural diff only shows semantic differences — changes to the actual values in the data model.
Reading the path labels
Every difference is labelled with a dotted path so you can locate it in the document without scanning manually:
| Path | Meaning |
|---|---|
name | the top-level key "name" |
limits.upload | the upload key inside the limits object |
tags[1] | the second element (index 1) of the tags array |
users[2].email | the email key of the third element of the users array |
For a deeply nested config file this lets you jump directly to the changed field rather than reading the whole tree.
Common use cases
- API response versioning — paste two responses from different API versions to see which fields were added, removed, or changed.
- Configuration review — compare a production config against a staging config to catch unexpected differences before a deploy.
- Test fixture maintenance — compare expected vs actual API output when a test fails, to see exactly which fields are wrong.
- Data migration checks — after transforming or migrating JSON records, diff a sample to confirm the transformation is correct.
Edge cases to know
Arrays are matched by position, not by a key or identity. If an item is inserted at the beginning of a long array, every subsequent element appears as changed because its index shifted. For array-of-objects data where order may vary, pre-sort by a stable key before diffing, or look only at the fields that matter rather than the full array.