JSON Diff – Compare Two JSON Documents Structurally | TrenTyx

trentyx@local:~/data-converters/json-diff $ run json-diff_

Compare two JSON documents by structure rather than by line. Key order, indentation and trailing commas of whitespace are ignored, so you only see differences that would change how a program reads the data. Match array items by position, by an id field, or as an unordered set — then export the result as an RFC 6902 JSON Patch.

Paste JSON in both panes. Key order and whitespace are ignored.
Paste JSON in both panes to compare.
0
added
0
removed
0
changed
0
unchanged values
original.json empty
changed.json empty
diff.txt waiting

      
+ added - removed ~ changed » moved

Why a Structural Diff Beats a Text Diff for JSON

A line-based diff compares characters, so it reports differences that do not exist as far as your program is concerned. Reformat a file, sort its keys alphabetically, or change two-space indentation to four, and a text diff lights up while the parsed value is identical. This tool parses both sides first and compares the resulting values, which means it reports only what a consumer of the data would actually notice.

  • Key order is irrelevant{"a":1,"b":2} and {"b":2,"a":1} are the same object.
  • Formatting is irrelevant — minified and pretty-printed documents compare equal.
  • Every difference gets a path$.profile.zip or $.items[2].qty, so you can find it in code rather than counting lines.
  • Type changes are called out91 becoming "91" is flagged as a type change, because it breaks strict consumers even though it looks identical.
  • Nothing leaves the browser — both documents are parsed locally with JSON.parse.

Array Comparison Modes

Arrays are where JSON comparison gets genuinely ambiguous, because only you know whether order carries meaning. Three modes cover the realistic cases:

  • By position — element 0 is compared with element 0. Correct for ordered data such as a route or a ranked list. Inserting one item near the front reports every later element as changed, which is accurate but noisy.
  • By key field — items are matched by a stable identifier such as id, so a record that moved is reported as moved rather than as a pile of changes. This is usually the right mode for collections coming out of a database.
  • Ignore order — the two arrays are treated as unordered sets, so reordering is invisible and only genuinely added or removed elements are reported. Useful for tag lists and permission arrays.

JSON Patch Output

The patch view emits an RFC 6902 operation list you can apply with any standard implementation. Where an array gained, lost or reordered elements, the whole array is emitted as a single replace rather than a sequence of indexed add and remove operations. That is deliberate: indexed array operations shift positions as they are applied, and a patch built from original indexes silently corrupts the document. Replacing the array is larger but correct.

Common Use Cases

  • Checking an API change — capture a response before and after a deploy and confirm only the intended fields moved.
  • Reviewing config drift — compare the JSON config in staging with production without arguing about key order.
  • Debugging a failing snapshot test — find which of 400 fields actually differs.
  • Auditing an export — verify that a migration preserved every record by matching on id.
  • Writing a patch request — generate the JSON Patch body for a PATCH endpoint from two example documents.

Frequently Asked Questions

Are my documents uploaded anywhere?

No. Both sides are parsed and compared in your browser with plain JavaScript. Nothing is transmitted, which matters when you are diffing production payloads.

Why is a reordered array reported as many changes?

Because the default mode compares by position, and after an insertion every later index holds a different value. Switch to by key field if your items have stable identifiers, or ignore order if order carries no meaning.

What is the difference between “changed” and a type change?

Both appear in the changed count. A plain change means the value differs but the JSON type is the same; a type change means the type itself moved, such as a number becoming a string or an object becoming null. Type changes are annotated in the change list because they break strictly typed consumers.

Can I ignore trivial differences?

Partly. You can treat numeric strings as numbers, ignore string case, and treat null, empty string and a missing key as equivalent. These tolerances apply to the comparison and therefore to the generated patch, so switch them off before exporting a patch you intend to apply.

How large can the documents be?

Multi-megabyte documents parse fine. The rendered output is capped at a few thousand lines so the page stays responsive; the counts above the output always reflect the full comparison.

Related Tools