Skip to content
DevTinyTools

JSON Diff Checker

Compare two documents and get a flat list of every difference with the path to it. Change one value, add a member, drop an array element — each shows up as its own row, so nothing hides inside a collapsed tree.

Runs entirely in your browser — your JSON is never uploaded.

0 chars
0 chars
No comparison yet. Paste two documents and press Compare JSON.

How to compare two documents

  • Paste the original document on the left and the updated one on the right. Either side can be a minified or an indented payload; formatting makes no difference to the result.
  • Press Compare JSON. Each difference is listed with a path such as $.items[1].quantity.
  • Use Ignore array order when the same values arrive in a different sequence and the sequence is not meaningful — a list of tags, for example.
  • Turn Ignore key order off when member order is part of the contract, such as a payload you sign or hash.

What counts as a difference

A value is compared after parsing, not as text. That single decision explains most of the behaviour:

  • Whitespace never counts. Indentation, line breaks and spacing cannot produce a difference.
  • Numbers compare numerically. 1 equals 1.0, and 1e3 equals 1000.
  • Types are respected. The string "42" is reported as a change against the number 42, with the type transition shown in the row.
  • A missing member differs from null. Removing a key and setting it to null are different states, and the list says which one happened.
  • Array positions are compared by index by default. Inserting an element at the front of a ten-item array reports ten changes, because every position shifted. Turn on “ignore array order” if that is not what you mean.

How to read a path

Paths start at $, the whole document. Members are joined with a dot when the key is a plain identifier, and with brackets and quotes otherwise — $["content-type"] rather than $.content-type, which would be ambiguous. Array elements always use an index: $.orders[2].items[0].sku.

The paths are a report format, not a query language, so they are copy-pasteable into a bug ticket and readable without tooling. They are close enough to JSONPath that most of the time you can paste one into a debugger and it resolves, but no evaluator is bundled here.

When key order really matters

JSON defines an object as an unordered collection of members, so a producer that reorders keys has not changed the document. Two consumers then disagree about that: code that compares data sees no change, and code that hashes bytes sees a different hash for identical data.

The second group is where signature verification, ETags and content-addressed storage live. If you are debugging a signature that stopped matching after a refactor, turn “ignore key order” off: an order-only difference is exactly the failure that does not show up in a normal comparison. The number precision guide covers the other half of the same problem, where a round trip silently rewrites the bytes.

What this page does not do

  • No JSON Patch output. The result is a change list for a human, not an RFC 6902 document.
  • No schema validation. Both sides have to be syntactically valid JSON; whether they match your schema is a separate question.
  • No three-way merge. Two documents, not base/ours/theirs. Merging is a different tool.
  • No side-by-side text alignment. The list is structural. For a character-level diff of formatted output, a text diff tool is the right instrument.

Where your data goes

Both documents are parsed and compared in this tab. Nothing is uploaded, nothing is written to a cookie or to localStorage, and no analytics event carries the content — only the fact that a page was viewed, handled by the site-wide tag. If you open the network panel you will see no request containing your JSON.

Frequently asked questions

Does this produce a JSON Patch (RFC 6902)?
No. The output is a list of changes with paths, meant to be read. Generating a patch is a different problem — it requires choosing between add, remove, replace, move and copy for each change, and the result is only useful if the consumer can apply it. The change list here is deliberately the human-readable version.
What does “ignore array order” actually match on?
Elements are matched by value: two items pair up when their members are equal regardless of key order. A matched pair is therefore identical, so an edited element cannot appear as “changed” — it shows up as one removed plus one added. That is the honest representation: under order-insensitive matching, a moved value and an edited value are the same observation.
Why is a reordered key only reported when I turn the option off?
Because for most work, member order is noise — two objects with the same members are the same data. Turn “ignore key order” off when order is part of the contract: signature verification, ETags, or a cache keyed on the serialised bytes. JSON itself defines no order, so anything depending on it is depending on the producer.
Are numbers compared as text or as numbers?
As numbers, after parsing. That means 1 and 1.0 compare equal, and -0 equals 0 — which matches how JSON prints them. It also means both documents went through a float round trip before comparison, so IDs above 2^53 may already be equal for the wrong reason.
How large can the two documents be?
Each side is limited to 2,000,000 characters. The comparison stops after 500 differences and says so, because a list of ten thousand rows is not a report — narrow the documents down and compare a subtree instead.