Skip to content

JSON Diff

Find structural differences between two JSON values.

A JSON diff compares two JSON values by structure, not by string. The tool above runs the diff in your browser; nothing leaves your machine.

Why structural diff beats text diff

A regular text diff of two JSON files reports differences in line content. That includes legitimate changes (a value flipped from true to false) but also irrelevant ones (key reorder, whitespace changes, a different indent style).

File A:                File B:
{                      {
  "name": "Alice",       "age": 30,
  "age": 30              "name": "Alice"
}                      }

Text diff: every line is "different."
JSON diff: nothing changed (same keys, same values).

A structural JSON diff parses both inputs into in-memory objects and walks the tree comparing nodes. Order doesn’t matter for object keys; whitespace doesn’t matter at all.

The output format

JSON diffs typically output one of three formats:

Path-based

Changes:
  - path: $.name
    from: "Alice"
    to:   "Alicia"
  - path: $.tags[2]
    added: "vip"
  - path: $.metadata.created
    removed

Each change names the JSON path (using JSONPath or similar dotted notation) and the operation. Easy to read; each line tells you exactly what changed.

JSON Patch format

RFC 6902 defines a standard “JSON Patch” representation:

[
  { "op": "replace", "path": "/name",         "value": "Alicia" },
  { "op": "add",     "path": "/tags/2",       "value": "vip" },
  { "op": "remove",  "path": "/metadata/created" }
]

The advantage: machine-readable. The same patch can be applied to the original to produce the modified version. Useful for sync, optimistic concurrency, and audit logs.

Side-by-side tree

A visual representation of the original and modified trees with changes highlighted. Easier for human review of complex diffs; not machine-readable.

The tool above uses the path-based form, one change per line: ~ path: old → new for a changed value, + path = value for an added key and - path (was value) for a removed one. It doesn’t emit JSON Patch or a side-by-side tree.

What counts as a change

The decisions a JSON diff has to make:

  • Object key order. JSON spec says order doesn’t matter; the diff treats {a:1,b:2} and {b:2,a:1} as equal.
  • Array order. JSON spec says order does matter; [1,2,3] and [3,2,1] are different. The tool above compares an array as one value: if anything inside it differs, it reports the whole old and new array on one line rather than element by element, and it has no “ignore order” option.
  • Number formatting. 1, 1.0, 1e0, and 1.00 are the same number. The parser normalizes; the diff doesn’t see them as different.
  • Trailing whitespace in strings. "hello" and "hello " are different strings.
  • Null vs missing. {"a": null} and {} are different — one explicitly has key a, one doesn’t.
  • Type changes. true vs "true" is a change; the diff reports the value change with explicit type info.

Array element diff

Array diff is the trickiest case. Consider:

A: [1, 2, 3, 4, 5]
B: [1, 9, 3, 4, 5]

The clear interpretation: index 1 changed from 2 to 9. But what about:

A: [1, 2, 3, 4, 5]
B: [1, 3, 4, 5]

Two valid interpretations:

  • “Index 1 (was 2) was deleted, the rest shifted.” — One delete, no other changes.
  • “Index 1 changed to 3, index 2 changed to 4, index 3 changed to 5, index 4 was deleted.” — Four changes.

A “minimal diff” gives you the first; a positional diff gives you the second. Most tools do something in between using a longest-common-subsequence (LCS) algorithm — same as text diff, but applied to array elements.

For arrays where order doesn’t matter (sets), a different algorithm runs: report which elements were added and which were removed, ignoring order.

When JSON diff is the right tool

  • Comparing two API responses. “Did the response actually change?”
  • Auditing changes to configuration. Comparing committed config snapshots.
  • Testing. A test that compares actual vs expected output is more robust with JSON diff than with text diff.
  • Synchronizing. Generating a JSON Patch to send “the diff” between client and server state.
  • Code review for JSON-bound files. Locale files, schemas, package metadata — all easier to review with structural diff.

When it’s not

  • JSON-like files that aren’t strict JSON. JSON5, JSONC (with comments), HCL, YAML — need their respective diff tools.
  • Files with intentional formatting. A pretty-printed schema where indent is part of the documentation. Text diff will catch indent changes; structural diff won’t.
  • Order-sensitive arrays where the diff “ignore order” option is wrong. Make sure you know what order semantics you want.
  • Diffing very large JSON. Multi-MB JSON in a browser-based tool will be slow. Server-side or streaming JSON diff tools handle this.

Common pitfalls

  • Comparing JSON that’s actually different formats. Make sure both inputs are valid strict JSON before diffing. Use JSON validator to confirm.
  • Treating null and missing keys as equivalent. Most JSON diffs distinguish them; some downstream consumers don’t. Know which behavior you want.
  • Order-sensitive vs order-insensitive arrays. Default-on or default-off varies by tool. Read the docs and test on your specific data.
  • Diffing through a wrapper. Many APIs return JSON inside a string field of a parent JSON. Diffing the outer JSON treats the inner string as opaque; you have to parse the inner string and diff that separately for full structural comparison.

For non-structural text comparison, see text diff. For JSON formatting before diffing, JSON formatter. For JSON validation, JSON validator.