Skip to content

JSON Diff & Compare

Compare two JSON files instantly in your browser. Side-by-side highlighting, RFC 6902 JSON Patch output, ignore noisy fields like timestamps and IDs. 100% private, no upload.

No Tracking Runs in Browser Free
Ignore paths:
Advanced Options
Array mode
Reviewed for RFC 6902/6901 compliance and edge cases including null vs missing keys, type drift, floating-point precision, and array key alignment. — Go Tools API Tooling Team · May 4, 2026

What is JSON Diff?

JSON Diff is a structural comparison of two JSON documents that respects JSON's data model — keys are unordered, types are strict, and arrays may be ordered or keyed. Unlike a text diff (which compares lines and reports key reorders or whitespace as differences), a JSON diff produces semantically meaningful results.

The canonical machine-readable form is JSON Patch (RFC 6902), an ordered ops array (add, remove, replace, move, copy, test) that transforms one document into another. Paths use JSON Pointer (RFC 6901). Closely related: JSON Merge Patch (RFC 7396) — simpler but cannot distinguish 'remove key' from 'set key to null'. This tool outputs RFC 6902.

Deep equality on JSON in JavaScript is harder than it looks. JSON.stringify(a) === JSON.stringify(b) fails on key reorder, misleads on -0 vs 0 (both stringify to "0"). A correct diff must walk both trees in parallel using key-set union, distinguish null from missing via the 'in' operator, and decide what 'equal' means for numbers (Object.is by default, epsilon for tolerance).

This tool runs entirely in your browser. Inputs never leave your machine. Safe for API responses, internal schemas, and proprietary configs.

Working with adjacent JSON tools? Format with JSON Formatter; convert with JSON to YAML and YAML to JSON. See our guide for advanced timestamp/ID filtering patterns.

// Two JSON documents that look different but are semantically equal
const a = '{"a":1,"b":2}';
const b = '{"b":2,"a":1}';

// Naive comparison — wrong
JSON.stringify(JSON.parse(a)) === JSON.stringify(JSON.parse(b));
// → false (key order differs)

// JSON Diff (this tool) — correct: key order is irrelevant
// → 0 differences

// JSON Patch (RFC 6902) for { "a": 1 } → { "a": 2 }
// [{ "op": "replace", "path": "/a", "value": 2 }]

Key Features

Side-by-Side + JSON Patch

Two views from one diff: visual highlighting for review, RFC 6902 patch for automation.

Ignore Noisy Fields

One-click presets drop /createdAt, /updatedAt, /*Id, /*At, requestId, traceId. Custom Extended JSON Pointer patterns supported.

Match Arrays by Key

Compare arrays of objects by an id field rather than by index — for K8s envs, package-lock entries, or any logically unordered list.

Type-Strict by Default

1 ≠ "1". null ≠ missing. Catch backend serialization drift the moment it lands in a test fixture.

100% Browser-Based

Inputs never leave your machine. No upload, no localStorage of JSON, no analytics on what you paste.

Share Link, Not Data

Share Link writes only your config to the URL. Your JSON inputs stay local.

Examples

API Response Regression

{"user":{"id":1,"name":"Ada","createdAt":"2024-01-01"}}
{"user":{"id":1,"name":"Ada Lovelace","createdAt":"2024-02-02"}}

Two changes (name + createdAt). Add /user/createdAt to Ignore paths and only the name change remains.

Config File Audit (Key Reorder)

{"a":1,"b":2,"c":3}
{"c":3,"a":1,"b":2}

Same data, different key order. JSON Diff treats key order as semantically irrelevant — diff is empty.

Array of Objects (Match by Key)

[{"id":1,"qty":3},{"id":2,"qty":5}]
[{"id":2,"qty":5},{"id":1,"qty":4}]

Switch Array mode to 'Match by key' with key=id. Without alignment every element looks changed; with alignment only qty on id=1 changes.

JSON Patch Output (RFC 6902)

{"items":[{"id":1,"price":29.99}]}
{"items":[{"id":1,"price":24.99}]}

Switch to the JSON Patch tab to get [{"op":"replace","path":"/items/0/price","value":24.99}] you can apply with fast-json-patch.

How to Use

  1. 1

    Paste both JSON documents

    Paste the original (left) and modified (right) JSON. Live diff renders as you type; large inputs (>200 KB) switch to a manual Diff button.

  2. 2

    Filter the noise

    Click a preset (Timestamps / IDs / Trace) or paste Extended JSON Pointer patterns into Ignore paths to drop irrelevant fields.

  3. 3

    Pick the view you need

    Side-by-Side for human review, JSON Patch (RFC 6902) for machine-applicable ops. Use Share Link to send the configuration to a teammate.

Common Diff Pitfalls

Key Order Noise (Text Diff Symptom)

If your diff tool reports {"a":1,"b":2} vs {"b":2,"a":1} as different, it's doing line diff, not JSON diff. JSON keys are unordered — this tool ignores key order automatically.

✗ Wrong
diff a.json b.json   # text diff: 'everything changed'
✓ Correct
JSON Diff (this tool): 0 differences

Null vs Missing Confusion

{"a":null} and {} are not the same. Treating them as equal masks real backend bugs.

✗ Wrong
{"a": null} == {}   # collapsed by some tools
✓ Correct
{"a": null} ≠ {}     # type-strict diff

Array Order Without Key Alignment

[{id:1},{id:2}] vs [{id:2},{id:1}] is not 'two changes' for a logical set. Sequential reports it as such; switch to Match by key.

✗ Wrong
Sequential diff: 4 modified
✓ Correct
Match by key (id): 0 differences

Type Drift (Number vs String)

Backends sometimes serialize IDs inconsistently — 42 vs "42". The tool flags these as 'type' modifications so you can spot the drift early.

✗ Wrong
{"id": 42} vs {"id": "42"}   # serialization bug
✓ Correct
Diff reports 'modified (type)' with both values

Floating-Point Precision

0.1 + 0.2 !== 0.3 in IEEE 754. With tolerance=0 (default), this is flagged. Set tolerance to 1e-9 if you intend numeric equivalence.

✗ Wrong
tolerance=0:  0.30000000000000004 ≠ 0.3
✓ Correct
tolerance=1e-9: equal

Timestamp & UUID Noise

createdAt, updatedAt, requestId, traceId mutate on every request. Use the Ignore paths presets to drop them.

✗ Wrong
Diff: 47 modifications (45 are timestamps)
✓ Correct
Add /createdAt, /updatedAt, /requestId to Ignore paths → 2 real changes

Common Use Cases

API Response Regression
Compare staging vs production responses; ignore timestamps and request IDs to surface only meaningful payload changes.
CI Snapshot Test Failures
Paste actual vs expected from a failing Jest/Vitest snapshot. Filter noise and find the real change in seconds.
package-lock / yarn.lock Conflicts
Resolve merge conflicts by aligning dependencies on name; key order and unrelated fields stop being noise.
K8s / Helm Values Audit
Match envs, volumeMounts, and ports by name. Catch unintended ordering vs real config edits.
i18n Translation Coverage
Diff en.json against zh.json structurally to find missing or extra translation keys without value-noise.
Terraform / CDK Plan Review
Compare plan output across runs; numeric tolerance handles floating-point arithmetic, ignore paths drop ARNs and timestamps.

Technical Details

RFC 6902 Compliant Patch Output
Generates valid JSON Patch ops (add/remove/replace) with RFC 6901 paths. Verified against fast-json-patch@3.x and rfc6902 npm packages.
Iterative Traversal
Explicit-stack traversal (no recursion) caps at 100,000 nodes and depth 64 to prevent stack overflow on adversarial inputs.
Object.is Numeric Equality
Default numeric tolerance is 0 — uses Object.is so -0 and +0 are distinguished. Set tolerance > 0 for epsilon-based equality.

Best Practices

Filter Before Reviewing
Add Ignore paths first (timestamps, IDs, trace fields), then read the diff. Reviewing noisy diffs trains the eye to skip — and miss — real changes.
Match-by-Key for Logical Sets
If your array represents an unordered set (envs, users, dependencies), Match by key. Sequential diff on logical sets is almost always wrong.
Share Link, Not Inputs
Use Share Link to send a colleague your filter configuration — never paste sensitive JSON into shared docs. The URL contains only the config.

Frequently Asked Questions

Why does my diff show everything changed when I only changed one field?
Three usual suspects: (1) different key order — JSON Diff treats key order as equivalent, but text diff tools don't; (2) timestamps/UUIDs/auto-IDs that mutate on every request — add them to Ignore paths; (3) array order, when by-index comparison shouldn't apply — switch Array mode to 'Match by key'.
How do I ignore timestamps and IDs in JSON diff?
Use the Ignore paths input above. Click the 'Timestamps' or 'IDs' preset for one-click filtering of /createdAt, /updatedAt, /*Id, /*At, /requestId. You can also paste your own Extended JSON Pointer patterns — one per line — for advanced filtering.
What's the difference between JSON Patch and a visual diff?
Visual (side-by-side) diff is for humans — review changes by eye. JSON Patch (RFC 6902) is for machines — a structured ops array (add/remove/replace) you can apply with fast-json-patch or rfc6902 npm packages. Same diff, two outputs.
Does JSON diff treat null and missing keys the same?
No. {"a":null} and {} differ — the first has an explicit null, the second has no key. Real systems behave differently for the two; this tool keeps them distinct.
How are arrays compared — by index or by key?
By index (Sequential) by default. Switch to 'Match by key' and provide a key field (commonly id) to align elements regardless of order. Use this for K8s envs, package-lock entries, or any list that's logically a set.
Can I export the diff as RFC 6902 JSON Patch?
Yes. The JSON Patch tab outputs a valid RFC 6902 ops array. If Ignore paths are set, the patch is filtered (the tab shows '(filtered: excludes N ignored paths)') and will not round-trip the originals exactly. Clear Ignore paths for a complete patch.
Is JSON Patch the same as JSON Merge Patch (RFC 7396)?
No. RFC 6902 (JSON Patch) is an ordered ops array — explicit and reversible. RFC 7396 (Merge Patch) is a single merge document — simpler but cannot represent removal differently from setting null. JSON Diff outputs RFC 6902.
How do I compare two large JSON files (>10 MB)?
Files over ~5 MB exceed practical browser memory. Live mode disables at 200 KB; for multi-megabyte files, use command-line jq or fast-json-patch in Node.
Does the tool send my JSON to a server?
No. All comparison runs locally in your browser. Inputs are never written to disk, network, localStorage, or URL parameters. Refreshing the page clears them. The Share Link button writes only your config (Array mode, Ignore paths) — never your data.
Why does 42 differ from "42" in the diff?
JSON Diff is type-strict: number 42 and string "42" are not equal. This catches backend serialization drift (some endpoints return numeric IDs, others return strings) — the diff labels it as 'type' modification.
Can I diff JSON with comments (JSONC) or trailing commas?
Standard JSON (RFC 8259) does not allow comments or trailing commas. This tool uses native JSON.parse, which rejects both. Strip comments first using JSON Formatter.
How do I compare nested arrays of objects by a key like id?
Set Array mode to 'Match by key' and enter id. Diff aligns by id values. v1 applies the same key field at every array depth; inner arrays without that field fall back to sequential and emit a warning chip.
Does the diff handle floating-point precision (0.1 + 0.2)?
Yes, with Numeric tolerance. Default is 0 with Object.is — so -0 vs +0 are flagged. Set tolerance to a small epsilon (e.g. 1e-9) and 0.1 + 0.2 will compare equal to 0.3. Tolerance applies only to numeric leaves.

Related Tools

View all tools →