JSON Diff: Compare Two JSON Documents

Paste two JSON documents to see which values changed, by path rather than by line. Formatting and key order do not count, and the result is also a JSON Patch.

Runs in your browser. Your input is not sent anywhere.

Treat arrays as unordered collections: [1, 2] equals [2, 1]. The order of object keys is always ignored.

Off by default. When on, the fields of this tool are kept in the local storage of this browser, unencrypted, until you turn it off.

Nothing to compare yet

Your result will appear here.

Keyboard shortcuts

Ctrl + Enter, ⌘ + Enter
Run the tool with the current input
Alt + Shift + C
Copy the result
Alt + Shift + X
Clear all fields

Shortcuts work while the focus is inside the tool. Every action is also available as a button.

How to use it

  1. Paste the older document into “Original JSON” and the newer one into “Changed JSON”.
  2. Turn on “Ignore the order of array items” if your arrays are sets, such as a list of tags or roles that may come back in any order.
  3. Read the differences: each one names the path of the value (a JSON Pointer), whether it was added, removed or changed, and the values before and after.
  4. Copy or download the JSON Patch if you want to apply the same change elsewhere or keep it as a record.

If either document is not valid JSON, the tool marks the field and selects the character where reading stopped. Keys that occur twice in one object are refused, because it is undefined which of the two values counts.

Worked example

A user record before and after an update. The keys are in a different order, and the price is written 1.50 in one and 1.5 in the other.

Original JSON
{
  "id": 7,
  "name": "Ada",
  "roles": ["admin", "dev"],
  "limits": { "rps": 10, "burst": 20 },
  "price": 1.50
}
Changed JSON
{
  "name": "Ada",
  "id": 7,
  "roles": ["dev", "ops"],
  "limits": { "rps": 25 },
  "price": 1.5,
  "active": true
}

The tool reports five differences. The moved keys and the two spellings of the price are not among them.

Differences
Removed  /roles/0       "admin"
Added    /roles/1       "ops"
Changed  /limits/rps    10 → 25
Removed  /limits/burst  20
Added    /active        true
JSON Patch
[
  {"op":"remove","path":"/roles/0"},
  {"op":"add","path":"/roles/1","value":"ops"},
  {"op":"replace","path":"/limits/rps","value":25},
  {"op":"remove","path":"/limits/burst"},
  {"op":"add","path":"/active","value":true}
]

Applied in order to the original, the patch produces the changed document. The second operation adds "ops" at index 1 because the first one has already removed "admin", so the array is ["dev"] at that moment. With array order ignored, "dev" matches wherever it is, and the patch appends "ops" with the path /roles/- instead.

How the comparison works

  • Objects are compared key by key. RFC 8259 calls an object an unordered collection (section 1), so the order of keys is ignored. A key that exists on one side only is added or removed; a key set to null is a changed value, not a removed key.
  • Arrays are compared in order. The tool first finds the largest number of items that stayed the same and in the same order (a longest common subsequence), using the difference algorithm of E. W. Myers, then pairs the remaining items between them position by position. That way an inserted item shows as one addition instead of a change to every item after it, and a record in which one field changed shows as that field.
  • Numbers are equal when their values are equal, the rule JSON Patch uses for its test operation (RFC 6902, section 4.6): 1, 1.0 and 1e0 are the same number, and so are 0 and -0. The tool compares the decimal digits exactly instead of converting them to floating point, so 12345678901234567890 and 12345678901234567891 are different, as they should be.
  • Strings are compared after decoding escapes, so "\u0041" and "A" are equal.
  • With “Ignore the order of array items”, each item matches an equal item anywhere in the other array. Items left over are paired only when both are objects or both are arrays; other leftovers are removed or added. The rule applies to arrays at every depth.

Paths are JSON Pointers (RFC 6901): one segment per key or index, with “~” written as ~0 and “/” as ~1, so the key a/b is /a~1b. An empty pointer names the whole document. In the list, removed and changed values carry their path in the original, added values their path in the changed document. The patch uses the index each operation finds when it runs, because RFC 6902 applies the operations one after the other; that is why the two can name different indexes for the same array item.

The patch uses only add, remove and replace. It does not detect moved or copied values; a value that moved to another key shows as removed in one place and added in the other.

The same check on the command line

Python compares parsed JSON the way this tool does for objects: key order is ignored and 1 equals 1.0, but arrays must be in the same order. It answers only yes or no.

Python
python3 -c "import json,sys; print(json.load(open(sys.argv[1])) == json.load(open(sys.argv[2])))" a.json b.json

jq can sort the keys of both documents so that a text diff ignores key order. It shows changed lines rather than paths, and jq 1.7 keeps most numbers as written, so 1.0 and 1 still appear as a difference.

jq and diff
diff <(jq -S . a.json) <(jq -S . b.json)

Common mistakes

  • Comparing JSON as text. Serializers are free to order keys and indent differently, so a text diff of two API responses often shows changes on every line when the data is the same.
  • Comparing after JSON.parse in JavaScript. Numbers become 64-bit floats, so integers above 2^53, such as 64-bit IDs, can round to the same value: in JavaScript, JSON.parse("12345678901234567890") === JSON.parse("12345678901234567891") is true.
  • Ignoring array order where it matters. For a list of steps or a sorted result, order is part of the data; turn the option on only for arrays that are sets.
  • Reading patch paths as original positions. Each operation sees the document as the operations before it left it, so after a removal the following indexes shift down by one.
  • Treating a missing key and a null value as the same. Many APIs do, but JSON does not: the tool reports the change between them.

Sources

Frequently asked questions

Are the documents I paste sent anywhere?
No. The comparison runs in your browser and nothing you paste is sent or stored, unless you turn on “Remember my input on this device”, which keeps it in this browser only. If this page shows ads, the ad script runs in the same page, but the tool never passes your input to it.
How do I compare JSON without regard to key order?
Paste both documents; key order is always ignored, and so are indentation, line breaks and the spelling of numbers. Only values count: the tool lists the paths whose values differ.
Can I compare JSON arrays without regard to order?
Yes. Turn on “Ignore the order of array items”. Each item then matches an equal item anywhere in the other array, at every depth, and the patch adds new items at the end of their array.
What is a JSON Patch and how do I apply it?
A JSON Patch (RFC 6902) is a list of operations such as add, remove and replace, each with a JSON Pointer path. Applied in order to the original document, the patch from this tool produces the changed one; with array order ignored, it produces a document that differs from it only in the order of array items. Most languages have a JSON Patch library, and APIs that support JSON Patch accept it in a PATCH request with the media type application/json-patch+json.
Why are 1 and 1.0 not reported as a difference?
Because they are the same number. JSON does not distinguish integers from decimals, and RFC 6902 compares numbers by value. If the spelling matters to you, for example in a signed document, compare the texts with the text diff instead.

Last updated: September 29, 2026