Two JSON documents can be byte-for-byte different and functionally identical — or look nearly identical and be structurally broken. Closing that gap is the entire point of a JSON diff, and it's a genuinely different problem than diffing two text files. If your two objects are short and you just want to paste two JSON objects into a browser tool and see the result, that guide is the click-by-click walkthrough. This one covers what's actually happening underneath: why a plain text diff misreads JSON, what a structural diff computes instead, the two IETF standards for representing a difference JSON that diff tools can store or apply as data, and where our own browser tool's honest limits sit. If your document is XML rather than JSON, the diffing problem looks different again — see the XML compare guide for namespace and attribute-order handling instead.
The Short Answer: What a JSON Diff Actually Compares
A JSON diff compares two JSON documents by structure and value — which keys were added, removed, or changed, and at what path inside the tree — instead of by which lines of text moved. A correct json comparison is invariant to object key order, invariant to whitespace and indentation, and, once numbers are normalized, invariant to equivalent numeric formats. It is not invariant to array order, because a JSON array is an ordered sequence and a JSON object is an unordered collection of key-value pairs — that's the definition in RFC 8259, not a convention any particular tool chose. Nearly every surprising result you'll get from a diff json tool traces back to that one asymmetry: objects don't care about order, arrays do.
That distinction is also why running two JSON files through a generic text differ — the
same diff command you'd use on two plain .txt files — routinely
produces a wall of red and green for documents that are, semantically, identical. The next
few sections cover exactly why that happens and how a real online json compare
tool avoids it.
Why a Plain Text Diff Lies About JSON
Feed two structurally identical JSON objects into a plain text differ and it will still report a change, because a text diff only knows about lines — it has no idea what a JSON object or array even is.
{ "a": 1, "b": 2 }
{ "b": 2, "a": 1 }
$ diff a.json b.json
1c1
< { "a": 1, "b": 2 }
---
> { "b": 2, "a": 1 } Two keys, same values, same document — and a naive attempt to compare two JSON files this way reports the whole line as replaced, because the key order changed and a text diff can only compare position, not meaning.
Numbers compound the problem. 1.0e6 and 1000000 are the same
number written two different ways — scientific notation versus a plain integer — and a
text diff sees two unrelated strings. 1.0 and 1 are the same kind
of mismatch one order of magnitude down: same value, different token. Neither pair equals
the other pair — a million is not one — but within each pair, a text diff flags a change
that a JSON-aware comparison should not.
Formatting adds pure noise on top of that: pretty-printed JSON versus minified JSON, 2-space indentation versus 4-space, a trailing newline at end of file versus none, CRLF line endings versus LF from a file that crossed from Windows to Linux. None of it changes a single value in the document, and all of it shows up as a diff in a tool that only understands text.
Two more structural quirks round out the list, and they get their own callouts because normalization alone — covered a few sections down — doesn't fix either one:
- Array insertion at index 0 shifts every later index. Insert a new first element into an array and a positional diff — one that compares index 0 to index 0, index 1 to index 1, and so on — reports every element as changed, because everything downstream of the insertion point moved one slot to the right.
- The escape-sequence trap.
"é"written as a single precomposed Unicode codepoint and"é"written as the letterefollowed by a combining acute accent render identically to a human reader, but they are different byte sequences and different JSON string values. Neither JSON parsing nor most diff normalization applies Unicode normalization (NFC/NFD) by default, so this one survives even a careful structural diff unless something explicitly normalizes it.
Structural vs Textual Comparison: The Real Distinction
Every JSON diff approach falls into one of two families, and knowing which one a tool uses tells you what it will and won't get wrong.
Textual diffing treats the input as lines of characters — usually the
Longest Common Subsequence (LCS) algorithm behind the classic Unix diff — and
reports insertions and deletions of lines. It's fast, language-agnostic, and works on
anything, which is exactly why it also can't tell a cosmetic reformat from a real data
change. Every failure mode in the section above is a textual-diff failure mode.
Structural diffing parses both documents into a tree first, then walks the
tree comparing nodes by key path rather than by line position —
user.address.city in document A is compared against the same path in document
B regardless of where either line landed after formatting. Object key order stops mattering
because the comparison isn't positional anymore; it's addressed by path. This is what every
serious json difference checker does under the hood, whether it's a CLI
tool, a JavaScript library, or a browser extension.
The practical shortcut that makes textual diffing usable on JSON anyway — instead of building a full structural diff engine — is normalization, covered next. That's the real distinction under any tool you use to compare 2 JSONs, from a five-line script to a full IDE plugin.
Normalize First: The Trick That Makes Text Diff Work on JSON
You don't need a structural diff engine to get a structurally correct result — you need to normalize both documents into one canonical text form first, then hand that to an ordinary text differ. Normalization means: parse the JSON, recursively sort every object's keys into a fixed order, and re-serialize with consistent whitespace. Two documents that are structurally identical but were serialized differently become byte-identical after normalization, and two documents with a real difference still show exactly that difference — nothing more, nothing less.
This is precisely what the Normalize button in the Diff Checker browser extension does for JSON: it parses the input, sorts object keys alphabetically (case-insensitive), and re-serializes with 2-space indentation. Arrays keep their original order by design — sorting array elements would silently change what the array means, since array order carries information that object key order doesn't. If the text isn't valid JSON, Normalize falls back to plain whitespace normalization instead of failing outright. Run Normalize on both sides before you diff and the key-order false positive from the section above disappears entirely — that single step is the most important habit in any serious json compare tool workflow, browser-based or not. The same button does format-appropriate work on non-JSON input too — sorting CSS properties, collapsing whitespace — which the guide to finding the difference between two strings walks through on plain text and code.
One honest caveat: because Normalize round-trips the document through parse and
re-serialize, it also collapses 1.0e6 and 1000000 down to the
same text — usually exactly what you want. But that round-trip passes through a JavaScript
number, and JavaScript numbers only represent integers exactly up to
253−1
(9,007,199,254,740,991). A large database ID or snowflake ID above that threshold can lose
precision in the round-trip. If your JSON carries big numeric IDs, treat a post-normalize
numeric diff on those specific fields with a healthy amount of suspicion and check the raw
values directly.
Where Normalization Still Isn't Enough
Key sorting and re-serialization solve the most common false positives, but three cases survive it.
Arrays don't get reordered — by design — so array insertions still cascade. Normalize sorting keys never touches array element order, because it can't: an array's order is data, not metadata. Insert a new element at the front of an array and every element after it is still, correctly, one index further along than it was before:
// before
["alpha", "beta", "gamma"]
// after inserting "new" at index 0
["new", "alpha", "beta", "gamma"] A naive positional comparison — index 0 vs index 0, index 1 vs index 1 — reports "alpha" replaced by "new," "beta" replaced by "alpha," "gamma" replaced by "beta," plus one addition, when what actually happened is a single insertion. This isn't a bug in normalization; it's the correct, literal reading of an ordered sequence. Fixing it requires a smarter array-matching strategy, covered a few sections down.
Numbers beyond safe-integer range, as covered above — round-tripping through a parser can silently change a huge ID's precision by a few digits, and a diff on the normalized output won't tell you the original raw values differed.
Unicode normalization forms aren't touched by JSON parsing or
re-serialization at all. JSON.parse and its equivalents preserve string
content exactly; they don't apply NFC or NFD Unicode normalization. Two strings that
display identically but use different Unicode representations of the same accented
character stay different after any amount of key-sorting and re-indentation, because the
difference lives inside a string value, not in the document's structure.
JSON Patch (RFC 6902): The Standard Diff Output
RFC
6902, JSON Patch, standardizes what a JSON diff looks like as data instead of as
colored lines on a screen — a JSON document you can store, transmit, or apply. Its media
type is application/json-patch+json, and a patch is a JSON array of operation
objects. Six operations are defined: add, remove,
replace, move, copy, and test.
[
{ "op": "replace", "path": "/user/name", "value": "Alice" },
{ "op": "add", "path": "/user/tags/-", "value": "verified" },
{ "op": "remove", "path": "/user/legacyId" }
]
Each operation's path is a JSON Pointer (RFC 6901) — a slash-delimited path
into the document, like /users/0/name for the name key of the
first element in a users array. A trailing - in an array path, as
in /user/tags/- above, means "append after the last element." Two characters
need escaping inside a pointer segment because they're also the pointer's own syntax:
~1 stands for a literal / in a key name, and ~0
stands for a literal ~.
Operations apply sequentially, in array order, and the whole patch aborts
if any single operation fails — there's no partial-apply mode. That makes JSON Patch
precise and auditable: you can see exactly which operation, at exactly which path, produced
exactly which change, and a test operation can even assert a value before
proceeding, so the patch fails loudly instead of applying against a document it no longer
expects.
JSON Merge Patch (RFC 7386) and Its null Problem
RFC
7386, JSON Merge Patch, takes a different, much simpler approach: media type
application/merge-patch+json, and the patch document mirrors the shape of the
thing it's patching, rather than listing operations.
{
"name": "Alice",
"email": null,
"address": { "city": "Berlin" }
}
Applying that patch sets name to "Alice", merges
city into the existing address object, and — this is the part
worth knowing cold — deletes the email key, because
null in a merge patch means "remove this." That convention is also the
format's one real limitation: since null is reserved to mean delete,
you can never use a merge patch to set a field's actual value to
null — there's no escape hatch for it in the spec. The second
limitation is arrays: a merge patch cannot patch inside an array at all — it can
only replace an array wholesale, value for value, because merge patch has no path syntax to
address "index 2 of this array" the way JSON Pointer does.
RFC 6902 vs RFC 7386: Which One to Use
Both are legitimate, standardized ways to represent a difference JSON that diff tools can hand off as data — they trade precision for simplicity in opposite directions.
| Property | JSON Patch (RFC 6902) | JSON Merge Patch (RFC 7386) |
|---|---|---|
| Media type | application/json-patch+json | application/merge-patch+json |
| Shape | Array of operation objects (add/remove/replace/move/copy/test) | Mirrors the target document's shape |
| Can set a value to null | Yes — replace with "value": null | No — null always means delete |
| Array edits | Addresses individual indices via JSON Pointer | Replaces the whole array, no partial edits |
| Readable by a human at a glance | Moderate — verbose but explicit | High — looks like the document itself |
| Best fit | API diffs, audit trails, precise programmatic patching | Config overlays, PATCH endpoints on REST APIs |
Reach for JSON Patch when you need an exact, ordered, auditable record of what changed — the kind of thing you'd log or replay. Reach for JSON Merge Patch when the patch itself should be easy for a person to write by hand, such as a small config override file, and you can live with its two constraints: no explicit nulls, no partial array edits.
Comparing JSON on the Command Line (jq, jd, dyff)
For a linux json diff or any terminal-first workflow, three tools cover almost every case.
jq: normalize, then diff
The canonical way to compare two json files from a shell is to normalize
both through jq and hand the result to diff:
diff <(jq -S . a.json) <(jq -S . b.json) jq's -S flag sorts object keys recursively before printing — the
exact CLI equivalent of the Normalize button covered above. Its limitation is the same one
normalization always has: jq -S has no smart array matching, so array
comparisons stay purely positional. It's the right first tool to reach for, and the wrong
one if your JSON has arrays that get reordered or gain elements mid-sequence.
jd: a diff tool built specifically for JSON and YAML
jd is a
CLI (and library) that diffs and patches JSON and YAML directly, with no jq
pipeline required. It's actively maintained, prints its own diff format by default, and can
also emit output as an RFC 6902 JSON Patch or an RFC 7386 JSON Merge Patch — useful when
you want a diff json result you can immediately apply somewhere else
instead of just reading. jd also ships a web UI for the same comparisons when you'd rather
not leave the browser.
dyff: path-based diffs for config and Kubernetes
dyff diffs
YAML and JSON and prints results as human-readable, path-based statements (Spruce
dot-syntax, like spec.replicas) instead of a raw structural dump — built
specifically for diffing Kubernetes manifests and Helm chart output, where a plain text
diff on rendered YAML is close to unreadable. It's installable via Homebrew.
All three sit next to the broader Linux/Unix diffing toolchain — if diff's own
flags and output format aren't second nature yet, the
diff command guide and the
unified diff format guide cover the syntax these
JSON-specific tools build on top of. For a broader survey of GUI and CLI options beyond
these three, see the Linux diff tool roundup.
Whether you compare JSON files locally with a one-off jq pipeline or compare 2
JSON files automatically inside a CI job with jd, normalizing before diffing is the same
rule either way.
JavaScript Libraries for Programmatic JSON Comparison
When the comparison needs to live inside test code, a CI check, or an application rather than a terminal, a library beats a CLI call — you compare JSON objects already in memory and assert on the result, instead of shelling out and parsing text output.
- jsondiffpatch — a deep-diff library with smart array matching (LCS-based, so it detects moves and insertions instead of treating every shifted index as a replacement), plus a text-diff mode for long string values. It can export its result as an RFC 6902 patch. This is the closest thing to a full structural differ in the JS ecosystem, and the one to reach for when array reordering is the specific problem you're fighting.
- microdiff — deliberately the opposite trade-off: under 1KB, zero dependencies, fast, and simple. It doesn't offer jsondiffpatch's array-matching options — a reasonable choice when you just need "did anything change and where" without the overhead.
- deep-diff — a widely used deep-equality/diff library that reports what changed (new, deleted, edited, array-changed entries) without producing an applicable patch. Good for logging or assertions, not for generating something you'd send over the wire.
- json-diff (the
andreyvitpackage on npm) — still widely depended on across the ecosystem, but its last publish was roughly three years ago. Treat it as maintenance-mode rather than actively developed, not as abandoned — plenty of production code still runs on it.
For a side-by-side look at plain equality checks rather than diffing —
JSON.stringify comparison, Lodash isEqual,
fast-deep-equal, and where each one breaks — see the dedicated
JavaScript object comparison guide.
And if the JSON you're comparing is really an array or a list of records rather than a
single object, the guide to JSON lists and arrays
covers parsing and diffing that shape specifically. On the Python side,
deepdiff with ignore_order=True covers the same ground the JS
libraries above do — see
comparing two files in Python for the
full method rundown, filecmp and hashlib included.
Which approach to reach for
Five approaches, one table: a quick reference for which json diff method actually fits the job in front of you, before the next section goes deep on the browser tool specifically.
| Approach | Structural? | Array matching | RFC 6902 output | Best for |
|---|---|---|---|---|
jq -S + diff | No — normalize, then line diff | Positional only | No | Quick one-off CLI checks |
| jd | Yes | Positional | Yes (or RFC 7386) | Scripted diffs that need a patch |
| dyff | Yes | Positional | No | Kubernetes and Helm manifests |
| jsondiffpatch | Yes | LCS-based — detects moves | Yes (exportable) | JS apps fighting array reordering |
| Diff Checker (browser) | No — normalize, then text diff | Positional | No | Fast, private, no-install compares |
Comparing Two JSON Files in the Browser
The Diff Checker Chrome extension is a fast, private way to diff JSON online — compare two JSON files right in your browser, with no CLI, no library, and no account required. Everything below is what it actually does today, verified against the current build.
- Format — Prettier-powered pretty-printing. JSON is one of the supported parsers, alongside JS, TS, HTML, CSS, YAML, Markdown, and GraphQL. It's a manual click, not an automatic on-paste behavior.
- Normalize — for JSON specifically, parses, sorts object keys alphabetically (case-insensitive), and re-serializes with 2-space indentation, exactly as described above; falls back to whitespace normalization on invalid JSON.
- Compare method — a dropdown with exactly three options: Smart Diff (the default), Ignore Whitespace, and Classic (LCS).
- Split or Unified view — side-by-side is the default; both panes are directly editable.
- Show Diff Only — a toggle with a context-lines selector (0, 1, 2, 3, or 5 lines) that collapses unchanged regions so a long file doesn't bury the two or three sections that matter.
- Wrap, Swap, and Copy Diff — line wrapping, one-click pane swap, and
copying the diff to your clipboard as plain text with
+/-prefixes. - History — past comparisons are stored locally in IndexedDB, nothing server-side.
- Open Files — accepts
.jsonplus.txt .js .jsx .ts .tsx .html .css .md .py .java .c .cpp .cs .go .rb .php .sql .yaml .ymland DOCX/XLSX, up to two files at a time, 50 MB hard cap per file. - Syntax highlighting via Monaco Editor, with JSON among 17 bundled languages.
- Keyboard — Alt+↓ jumps to the next change, Alt+↑ to the previous one. These are the only two custom shortcuts the extension defines.
- AI Summary — optional and off by default. Bring your own OpenAI API key, stored locally, and it produces a plain-English summary plus a key-changes list. Turning it on means the compared content is sent to OpenAI — worth knowing before enabling it on anything sensitive.
- Compare Tabs Source — an extension-only feature that pulls the HTML source of open browser tabs directly into the comparison, no copy-paste.
Everything above the AI Summary bullet runs entirely client-side — no network call happens anywhere in the diff path, nothing you paste or open is uploaded. The one thing that does contact a server is the opt-in AI Summary, and only after you've supplied your own key. There's also a browser-only version of the same tool at diffchecker.pro/compare if you'd rather not install an extension at all.
Here's the honest boundary, stated plainly rather than buried in fine print: this is a fast, normalize-then-text-diff tool, not a full structural JSON differ. Format plus Normalize plus Smart Diff handles the overwhelming majority of real-world JSON comparison — pasting two API responses, checking a config change, eyeballing what a migration script produced — and it does it instantly, privately, with no upload. What it does not do: true array-order-insensitive comparison (arrays stay positional by design, as covered above), JSON-schema validation or awareness, RFC 6902/7386 patch output, a three-way merge, applying a patch back onto a document, or exporting the diff to a file. If you specifically need machine-readable patch output or genuine array-identity matching — not just position — that's exactly the gap jd or jsondiffpatch from the sections above are built to fill. Many other online json comparator options draw this line differently: Diffchecker.com, for instance, gives you a free web tier for basic compares but reserves desktop apps and permanent sharing links for its Pro + Desktop tier at $15/month (Legal at $20/month, Enterprise at $40/month, as of 2026). Diff Checker's browser extension has no paid tier at all — what's described in this section is the entire feature set, free, with no account.
Array Matching: Why "Smart" Diffs Disagree
Ask three different JSON diff tools to compare the same two arrays and you can genuinely get three different answers, and it isn't a bug in any of them — it's because array diffing has no single correct algorithm, only strategies with different trade-offs.
Positional matching compares index 0 to index 0, index 1 to index 1, and
so on. It's what jq -S piped into diff does, and it's what our
extension's Normalize step preserves by leaving array order untouched. It's simple and
predictable, and it's the strategy that makes a single insertion at the front of an array
look like every element changed, as shown earlier.
LCS-based matching — the approach jsondiffpatch takes — treats the array like two sequences and finds the longest common subsequence between them, the same core idea behind text-diff algorithms applied to array elements instead of lines. It correctly identifies "one element was inserted" instead of "everything shifted," as long as the elements themselves are directly comparable.
A third strategy, common in tools built for arrays of objects specifically, is
identity-key matching: match array elements by a stable field like
id rather than by position or content similarity, so an object that moved from
index 3 to index 0 is recognized as "moved," not "removed and a different one added." None
of the CLI or library tools covered in this guide default to that strategy automatically —
it typically requires telling the tool which field is the identity key, because nothing in
JSON itself marks one.
The takeaway: when two json compare tool outputs disagree on the same array change, check which matching strategy each one uses before assuming either is wrong. They're usually both computing a correct answer to two different questions.
Where JSON Diffs Show Up in Real Work
The theory above earns its keep in a handful of recurring situations.
API contract testing. Comparing a v1 and v2 response body for the same endpoint is how you catch a renamed or missing field before a client breaks on it in production — exactly the case a JSON object comparison is built to catch, and one where key-order noise from a re-ordered serializer would otherwise bury the one field that actually changed.
Config drift. tsconfig.json, package.json,
CloudFormation templates, Kubernetes manifests rendered as JSON — diffing a live config
against its source of truth surfaces exactly what an environment override or a manual edit
changed. This is dyff's specific reason for existing, and it's a case where
diffing two file versions in git gets
noisy fast if the JSON isn't normalized first — a re-formatted file with zero real changes
still shows as a full rewrite in git diff unless you normalize before
comparing.
Code review. A pull request that touches a JSON config or fixture file is one of the more error-prone diffs to review by eye, because a reformat and a real change look identical at a glance in a raw text diff. Running the before/after through Normalize first turns that review from "scan 200 lines for the two that matter" into "read the two lines that changed."
Migrations. Moving records between systems — a SQL export reshaped into
MongoDB documents, a v1 API schema migrated to v2 — means verifying every field transformed
correctly, field by field, often across thousands of records where eyeballing isn't an
option and a scripted diff (jq in a loop, deepdiff in a Python
validation script, jsondiffpatch in a Node test) is the only realistic approach. When the
migration spans formats — JSON on one side, CSV or SQL rows on the other — the broader
playbook on comparing structured data sets
covers when to flatten to rows before diffing.
Comparing individual values correctly — numbers,
strings, nulls — matters even more at that scale, since a single silent type coercion
during migration can look identical to the human eye and still be structurally wrong.
Frequently Asked Questions
How do I compare two JSON files?
Three routes cover almost every case. In the browser, open or paste both documents
into a diff tool, hit Normalize so object keys sort into the same order on both
sides, then Compare — that's the fastest way to diff JSON online, with nothing to
install and nothing uploaded. On the command line, piping jq -S output
for both files into diff runs the same
normalize-then-compare in one line, and jd a.json b.json can compare 2
JSON files natively without the jq pipeline. In application code,
jsondiffpatch or microdiff returns the result as data you can assert on inside a
test. Whichever route you take, normalize first: skipping that step is what makes a
text differ report a wall of red and green instead of the difference JSON documents
actually have.
What's the real difference between comparing JSON and comparing plain text?
A text diff compares two files line by line and knows nothing about JSON's structure, so it reports a change whenever a line moves — even when the underlying data is identical. A JSON diff compares by structure and value instead: which keys were added, removed, or changed, and at what path. That makes it invariant to object key order and formatting, but not to array order, because JSON objects are unordered collections of key-value pairs while JSON arrays are ordered sequences — that asymmetry is why arrays and objects behave differently under every JSON diff tool. In practice the two approaches can disagree completely about the same pair of files, and only one of them is answering the question you actually meant to ask.
Why does {"a":1,"b":2} show as different from {"b":2,"a":1} in a text diff?
Because a plain text diff compares lines, not meaning, and reordering the keys changes the line's text even though it doesn't change what the object represents. JSON objects are unordered by definition, so both objects are the same document. The fix is normalization: parse both documents, sort every object's keys into a fixed order, and re-serialize before diffing. Once both sides use the same key order, a plain text diff on the normalized output reports zero changes for these two objects, exactly as it should.
What is JSON Patch (RFC 6902) and when should I use it instead of JSON Merge Patch?
JSON Patch (RFC 6902) represents a diff as an ordered array of operations — add,
remove, replace, move, copy, and test — addressed by JSON Pointer paths like
/users/0/name, with media type application/json-patch+json.
It applies sequentially and aborts entirely if any operation fails, which makes it
precise and auditable. JSON Merge Patch (RFC 7386) is simpler: the patch mirrors the
target document's shape and null means delete a key, but that convention
means you can never set a value to null on purpose, and it can only
replace arrays wholesale rather than editing inside them. Use JSON Patch when you need
an exact, ordered record of what changed; use Merge Patch when the patch should be
small and easy for a person to write by hand, and you can live with its two
constraints.
How do I diff two JSON files on Linux from the command line?
The standard Linux JSON diff recipe combines jq with diff:
diff <(jq -S . a.json) <(jq -S . b.json). The -S flag
recursively sorts object keys before printing, which eliminates key-order false
positives before diff ever runs — jq's limitation is that it
has no smart array matching, so array comparisons stay purely positional. For JSON- and
YAML-native diffing without a jq pipeline, jd is a
maintained CLI and library that can also emit RFC 6902 or RFC 7386 output. For config
and Kubernetes-style JSON/YAML, dyff prints human-readable, path-based
results instead of a raw structural dump, and installs via Homebrew.
Why do different JSON diff tools disagree about the same array change?
Because array diffing has no single correct algorithm — only strategies with different
trade-offs, and tools default to different ones. Positional matching compares index 0
to index 0 and so on; it's simple but makes a single insertion at the front of an array
look like every element changed. LCS-based matching, the approach jsondiffpatch takes,
finds the longest common subsequence between the two arrays and correctly spots
insertions instead of a full shift. Identity-key matching compares array elements by a
stable field like id rather than position, catching moves that the other
two strategies would read as delete-plus-add. None of the tools covered in this guide
default to identity-key matching automatically — it has to be configured, because
nothing in JSON itself marks a field as an identity key.
What is the best JSON diff tool?
There isn't a single winner — there's a best fit per job, and the split is clean. For
a quick visual check with nothing to install, a browser-based JSON difference checker
wins: paste both sides, normalize, read the highlighted result. When you compare JSON
files inside a script or a CI job, jq -S piped into diff
covers the simple cases and jd covers the ones that need RFC 6902 or
RFC 7386 patch output. For application code, jsondiffpatch handles the array
reordering that positional tools get wrong, while microdiff wins on bundle size when
you only need to know that something changed. Before you trust any online JSON
comparator, check two things: whether it sorts object keys for you, and whether it
compares your files entirely inside your own browser or ships them to a
server first. That second question matters just as much whether you compare 2 JSONs
by hand once or two hundred in a nightly pipeline.
Does comparing JSON in the Diff Checker browser extension upload my data anywhere?
No — the diff itself runs entirely client-side, inside your browser tab, with no network call anywhere in the comparison path. Format, Normalize, Compare, and History all work offline against local IndexedDB storage on your machine. The one feature that does contact a server is the optional AI Summary, which is off by default and requires you to supply your own OpenAI API key before it sends the compared content to OpenAI for a plain-English summary. Every other feature — including comparing two JSON files up to 50 MB each — never leaves your device.