JSON Diff

Compare two JSON documents field by field. Ignores key order and formatting so you only see real changes: added, removed, and changed values at any depth. Runs entirely in your browser.

How to use the JSON Diff

  1. Paste or type your original JSON into the left textarea, or click Open to upload a .json/.txt file.
  2. Paste or upload the changed JSON into the right textarea.
  3. Click "Compare JSON" to run the comparison.
  4. Review the summary bar for a quick count of added, removed, and changed fields.
  5. Expand or collapse nodes in the diff tree to drill into nested changes — changed values show old → new inline.

If you need a side-by-side editable view instead of a read-only diff tree, use the JSON Editor's built-in Compare mode — it lets you edit both sides and copy values across while diffing.

About the JSON Diff

Diffing two JSON documents as text does not work. Reorder two keys and a text diff reports every line between them as changed. Reformat one side and it reports the entire file as changed. Neither of those is a real difference — JSON object key order carries no meaning, and neither does whitespace.

This tool parses both documents and compares the resulting structures instead of the characters. The output is a tree of what was actually added, removed, or changed, at whatever depth the change occurred, with old and new values shown side by side.

When you'd use it

  • Comparing an API response before and after a deploy to see exactly which fields changed.
  • Checking what a migration script did to a config document.
  • Finding the difference between a working request body and one the server rejects.
  • Auditing two environments — staging versus production settings, or two tenants' configuration.
  • Reviewing a lockfile or generated JSON artifact where a text diff is unreadable.

A structural diff ignores key order

These two documents are identical to a JSON parser. A text diff would report four changed lines; a structural diff reports none.

Left

{
  "name": "Ada",
  "team": "Platform",
  "active": true
}

Right

{
  "active": true,
  "team": "Platform",
  "name": "Ada"
}

What a real change looks like

Added, removed, and changed fields are reported separately, with the old value struck through.

Left

{
  "plan": "free",
  "seats": 3,
  "trialEndsAt": "2026-01-01"
}

Diff result

~ plan:        "free" -> "pro"
~ seats:       3 -> 25
- trialEndsAt: "2026-01-01"
+ billingEmail: "ops@example.com"

How arrays are compared

Arrays are the hard part of any structural diff, because there is no universally correct answer. This tool compares arrays by index: element 0 against element 0, element 1 against element 1. That is predictable and fast, and it is the right behaviour when the array is positional — coordinates, ordered steps, a fixed-length tuple.

It is the wrong behaviour when the array is really an unordered set of records that happens to have been serialised in a different order. Inserting one item at the front of a 50-element list shifts every subsequent index, and the diff will report all 50 as changed even though 49 of them merely moved.

When that happens, sort both sides by a stable key before comparing. The JSON Editor's query bar can do this in one expression, and the result is a diff that reflects what actually changed rather than what moved.

Reading the output

Every node in the result tree carries one of four states.

  • Added — the key exists on the right but not the left. Shown in green with the new value.
  • Removed — the key exists on the left but not the right. Shown in red with the value that disappeared.
  • Changed — the key exists on both sides with different values. Shown in amber as old arrow new.
  • Unchanged — identical on both sides. Collapsed out of the way so the differences stand out; parent nodes containing changes stay expanded.

Type changes versus value changes

A field going from the number 3 to the string "3" is reported as a change, not as equal. This is deliberate and it catches a real class of bug: serialisation layers that quietly stringify numeric ids, booleans that arrive as "true", and null becoming the empty string are among the most common causes of a client that works against one environment and breaks against another.

The same applies to null versus a missing key. Those are different states — one says "this field is explicitly empty", the other says "this field was not sent" — and APIs frequently treat them differently, so the diff keeps them distinct.

Frequently asked questions

Why does it say nothing changed when the two files clearly differ?
Because the difference was formatting or key order, neither of which changes the data. That is the point of a structural diff. If you need to compare the literal bytes — because a signature or checksum depends on them — use the Text Diff tool instead.
Can I compare two files instead of pasting?
Yes. Each panel has an Open button that accepts .json and .txt files, and the file is read locally by your browser rather than uploaded.
What if one side is invalid JSON?
The comparison stops and reports the parse error with its position, because there is no meaningful structural comparison against something that is not JSON. Fix it in the JSON Editor — its Repair function handles the common cases — and then compare.
Does it handle very deep nesting?
Yes, the comparison recurses to arbitrary depth. Very deep documents produce a tall result tree, so collapse the branches you are not interested in to keep it navigable.
I need to edit while comparing. Can I?
This tool renders a read-only result. The JSON Editor has a Compare mode that diffs two editable panels and lets you copy values across between them, which is the better fit when you are reconciling two documents rather than just inspecting the difference.

Related tools