Compare JSON Online
100% in your browser
Your data is never uploaded. All processing happens locally on your device.
Read privacy policy →Last updated: 2026-09-17
Paste two JSON documents to compare them side-by-side with aligned lines and highlighted changes. Jump between changes with next/prev, filter by type (added, removed, modified), and export a markdown report or JSON Patch. Semantic diff is on by default — key order does not matter. Everything runs locally in your browser.
What this tool does
Compares two JSON documents side-by-side with aligned lines and highlighted changes. Semantic diff is on by default, meaning key order does not matter. You can filter changes by type, jump between them with next and prev, ignore specific paths with glob patterns, and export a markdown report or JSON Patch (RFC 6902). All processing is local.
Example
Left (before):
{"order":{"id":42,"status":"pending","total":29.99,"items":[{"sku":"A1","qty":2}]}}Right (after):
{"order":{"id":42,"status":"shipped","total":29.99,"items":[{"sku":"A1","qty":3}],"shippedAt":"2024-01-15"}}Changes shown:
order.status: modified —"pending"→"shipped"order.items[0].qty: modified —2→3order.shippedAt: added —"2024-01-15"
The side-by-side view aligns both documents by path and highlights each change in context.
Comparing API responses
When comparing two API responses from different requests, several fields may change on every call: timestamps, request IDs, pagination cursors, and rate-limit headers. Use the Ignore paths option to exclude these from the diff.
For example, to ignore updatedAt at any nesting level and requestId at the root:
*.updatedAt, $.requestIdGlob patterns supported: * matches any path segment, ? matches any single character. Multiple patterns are comma-separated.
Comparing configuration files
Configuration files often change in small ways between environments. Paste the development config on the left and the production config on the right to see exactly which keys differ. Key order is ignored by default, so reformatted configs do not produce noise.
For arrays of objects like server pools or feature flags, switch array matching to by key so reordered items do not show as changes. The tool auto-detects common key fields (id, _id, uuid, key, name) or you can specify one.
Filtering changes
The filter panel lets you show or hide changes by type:
| Filter | What it shows |
|---|---|
| Added | Keys or array elements present only in the right document |
| Removed | Keys or array elements present only in the left document |
| Modified | Keys where the value changed between left and right |
| Moved | Array elements that changed position (only in index mode) |
Click any change to scroll both panels to that position.
Sharing comparisons
The Share button encodes both JSON inputs in the URL hash (the fragment after #). The data stays in the URL — it is never sent to a server. Anyone who opens the link sees the same comparison with the same inputs. This is useful for sharing a specific diff in a pull request, chat, or issue tracker without attaching files.
Do it in code
JavaScript (jsondiffpatch):
const { DiffPatcher } = require('jsondiffpatch');
const differ = new DiffPatcher({ objectHash: (item) => item.id });
const delta = differ.diff(leftObj, rightObj);
// Apply the delta to produce a side-by-side view
const { formatters } = require('jsondiffpatch');
const html = formatters.html.format(delta, leftObj);Python (deepdiff):
from deepdiff import DeepDiff
diff = DeepDiff(left_dict, right_dict, ignore_order=True)
print(diff.to_json())CLI (jd):
jd -t json file1.json file2.json
# Or with jq for a quick sorted comparison:
diff <(jq -S . file1.json) <(jq -S . file2.json)Common mistakes when comparing
- Forgetting to ignore volatile fields. Timestamps, request IDs, and counters change on every request and produce noisy diffs. Add them to Ignore paths.
- Comparing arrays by index when items are reordered. If array items represent unordered collections, switch to by key or as unordered set mode. Index mode reports every position change as a modification.
- Not using loose type comparison for cross-system diffs. Systems that serialize values differently (string vs number) produce false positives. Enable loose type comparison to treat
1and the string1as equal. - Ignoring float tolerance for computed values. Floating-point arithmetic can produce tiny differences (e.g.
0.1 + 0.2vs0.3). Set a tolerance to avoid reporting these as changes. - Comparing minified vs formatted JSON. The diff is semantic, not textual, so whitespace does not matter. But if you want to catch formatting changes, use a text diff tool instead.
- Expecting key order to show as a change. By default, key order is ignored. Disable semantic diff if you need order sensitivity.
- Sharing links with sensitive data. The Share button puts both JSON documents in the URL. Anyone with the link can decode them. Do not share links containing secrets, credentials, or personal data.
Understanding the change summary
The summary bar at the top of the comparison shows counts for each change type: added, removed, modified, and moved. These counts reflect the semantic diff, not line counts. A single modified value at a deep path counts as one change, not dozens of changed lines. The summary updates live as you toggle filters, so you always know how many changes of each type are visible.
Exporting comparison results
Three export formats are available:
- Markdown report: a structured document with a summary table and a list of every change, suitable for pasting into a pull request description or issue comment. Each change includes its path, type, and before and after values.
- JSON Patch (RFC 6902): a machine-readable array of operations (add, replace, remove) that can be applied programmatically to transform the left document into the right document. Use this when you need to communicate changes to another system or apply them in a pipeline.
- Copy as JSON: copies the raw delta object produced by the diff engine, which includes the full structural difference tree. This is useful for custom processing or when you need the internal representation.
Comparing database snapshots
Database export comparison is a common use case. Export two snapshots as JSON, paste them on each side, and the tool shows which rows were added, removed, or modified. If the export includes array indices that shift when rows are inserted or deleted, switch to by key matching using the primary key field so rows are matched by identity rather than position.
For large database exports with hundreds of rows, the comparison runs in a Web Worker to avoid freezing the page. The side-by-side view is virtualized, so only visible rows are rendered.
Comparing schema migrations
When a schema changes between versions, comparing the old and new schema JSON shows exactly which fields were added, renamed, or removed. Use the ignore paths feature to skip metadata fields like $schema or id that change between versions but are not semantically relevant to the migration.
Schema migration comparisons benefit from the change tree view, which groups changes by parent path. For a JSON Schema document, changes under properties show new or removed fields, while changes under required show which fields became mandatory or optional. The markdown export captures this in a format suitable for a migration changelog or release notes.
Comparing i18n translation files
Internationalization files are JSON objects where keys are translation identifiers and values are localized strings. Comparing two language files or two versions of the same language file shows which translations were added, which were removed, and which strings changed. Key order is ignored, so alphabetically sorted files and insertion-ordered files compare the same way.
For arrays of pluralization variants, switch to by key matching if the array elements have identifiers, or use index matching if positional order matters for the plural rules. When comparing a base locale against a target locale, added keys in the base file represent missing translations in the target, and removed keys represent obsolete translations that should be cleaned up.
Comparing feature flag configurations
Feature flag systems store their configuration as JSON objects where each flag has a name, enabled state, rollout percentage, and targeting rules. Comparing two versions of a flag configuration shows which flags were toggled, which targeting rules were adjusted, and which rollout percentages changed. Because flag configurations are typically nested objects with arrays of rule conditions, the by key matching mode helps when rules are reordered.
The markdown export is particularly useful here because it produces a changelog that can be attached to a deployment ticket or change request, documenting exactly which flags changed and how.
Comparing package manifests
Package manifests like package.json or pyproject.toml (when serialized to JSON) can be compared between branches to see which dependencies were added, updated, or removed. Version strings are compared as strings, not semantic versions, so a change from ^1.0.0 to ^1.1.0 shows as a modified value. Script entries, dependency lists, and configuration sections all diff cleanly because the comparison is semantic and key order does not matter.
When comparing lockfiles, which can be large and deeply nested, the Web Worker ensures the comparison does not block the page. The change tree view groups dependency changes under their parent path (dependencies, devDependencies, peerDependencies), making it easy to categorize additions and removals.
Comparing CI pipeline definitions
Continuous integration pipelines defined as JSON (GitHub Actions workflows stored in JSON form, GitLab CI configurations exported as JSON) can be compared between branches to review changes before merging. Job definitions, step sequences, environment variables, and matrix configurations all appear as nested objects and arrays. Steps that were reordered are detected as moved entries when using index matching, or as identical when using set matching.
Comparing API request payloads
When debugging API issues, comparing the request payload that works against the one that fails is a quick way to spot the difference. Paste both payloads and the side-by-side view highlights every field that differs. This is especially useful when the difference is subtle — a string versus a number, a missing optional field, or a nested object with an extra key.
Performance and large documents
The comparison engine handles large JSON documents efficiently. Inputs over 200KB are parsed and diffed in a Web Worker, which runs on a separate thread so the main thread stays responsive. The side-by-side view uses virtualized rendering — only the visible portion of each document is rendered in the DOM, so scrolling through a 50,000-line file does not lag.
The diff algorithm itself is based on jsondiffpatch, which uses a recursive object comparison with move detection. For most real-world JSON (configuration, API responses, database exports), the comparison completes in under a second. Pathological inputs with thousands of array elements that are all different can take longer, but the Web Worker ensures the page never freezes.
How the side-by-side view works
The side-by-side view renders both documents as formatted JSON with matching paths aligned on the same horizontal line. Added lines are highlighted on the right side, removed lines on the left, and modified lines on both sides with the old and new values shown. Clicking a change scrolls both panels to the aligned position. The next and prev buttons step through changes in path order, so you can review every difference without scrolling manually.
Edge cases handled
- Semantic diff ignores key order by default —
{"a":1,"b":2}and{"b":2,"a":1}are identical. - Arrays can be matched by index, by a key field (auto-detected), or as unordered sets.
- Glob patterns in Ignore paths support
*and?wildcards for flexible path exclusion. - Loose type comparison converts numeric and boolean strings to their typed equivalents before diffing.
- Float tolerance rounds numbers to a specified precision before comparing.
- Large files (over 200KB) are processed in a Web Worker to keep the UI responsive.
- The markdown report includes a summary count and a list of every change with its path and values.
- JSON Patch output follows RFC 6902 with add, replace, and remove operations.
- Smart paste auto-repairs broken JSON on either side with a notice, so you can compare malformed inputs.
- The swap button exchanges left and right inputs, reversing the direction of added and removed changes.
- Both inputs are validated before comparison; if either side is invalid JSON, an error is shown with the position.
- Null and undefined values are treated as distinct: a field set to null is different from a missing field.
- The comparison treats empty objects and empty arrays as values, so removing an empty object shows as a removal.
- Deeply nested paths are displayed with dot notation for object keys and bracket notation for array indices.
- The change tree expands to show the full path hierarchy, letting you collapse parent nodes to focus on specific subtrees.
- Reordering object keys produces zero changes when semantic diff is enabled, which is the default behavior.
- Unicode text in string values is preserved and displayed correctly in both the tree and side-by-side views.
- The markdown export uses fenced code blocks for readability when pasted into GitHub, GitLab, or other markdown renderers.
- Mixed types at the same path (e.g. string in one document, number in the other) are reported as modified, not as a removal and addition.