JSON Diff
Compare two JSON documents semantically.
// Why a semantic diff helps
A plain text diff reports every reordered key and every reformatted line as a change. When a config file, API response or translation bundle is reorganised, that noise hides the edits that matter. This tool parses both documents first: objects align by key, and arrays align with a longest-common-subsequence pass that still pairs elements carrying the same id or _id after they move. Whitespace, indentation and key order therefore do not show up as changes.
// What the three options change
- >--ignore-array-order — Matches array elements by content instead of by position, so reordering alone does not create changes.
- >--sort-keys — Displays object keys in a stable, sorted order without treating the original order as a difference.
- >--only-changes — Folds unchanged stretches into a single marker and keeps the rows around each difference block.
// What an aligned result looks like
IN
LEFT: {"name": "CoreJSON", "version": "0.4.0", "tls": false} RIGHT: {"name": "CoreJSON", "version": "0.5.0", "tls": true, "openSource": true}
OUT
{ | { "name": "CoreJSON", | "name": "CoreJSON", "version": "0.4.0", | "version": "0.5.0", "tls": false | "tls": true, | "openSource": true } | }
Each line shows the left cell, then the right cell, in the order they appear in the result pane. Changed rows carry +, - or ~ and the header counts difference blocks.
// Common questions
Is this a text diff or a data diff?
A data diff. Both documents are parsed first, so whitespace, indentation and object key order do not create false changes. Invalid JSON is rejected with a line and column for the side that failed.
How are arrays compared?
By default a longest common subsequence aligns elements by position. Elements with the same id or _id are paired even after they move, and adjacent primitive removals and additions are reported as one modification. Turn on --ignore-array-order to match by content instead.
What happens if one side is invalid JSON?
The comparison stops and the failing side shows the parser message with a line and column. Fix that side and the rows update automatically.