JSON Diff — How to Compare Two JSON Objects for Differences
Whether you are checking if an API response changed between deployments, verifying a test snapshot, or debugging why two "identical looking" config files behave differently, you need a reliable way to diff JSON. Naive string comparison fails the moment key order changes. This guide covers the right way to compare JSON objects.
Why String Comparison Is Not Enough
Two JSON objects can represent identical data but produce different strings if key order differs:
const a = { name: "Priya", age: 29 };
const b = { age: 29, name: "Priya" };
JSON.stringify(a) === JSON.stringify(b); // false — but the data is identical!
console.log(JSON.stringify(a)); // {"name":"Priya","age":29}
console.log(JSON.stringify(b)); // {"age":29,"name":"Priya"}To correctly say these are "the same", you need deep equality — a comparison that checks matching keys and values regardless of order, recursively into nested structures.
Writing a Deep Equality Check
function deepEqual(a, b) {
if (a === b) return true;
if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) {
return false;
}
const keysA = Object.keys(a);
const keysB = Object.keys(b);
if (keysA.length !== keysB.length) return false;
return keysA.every(key =>
Object.prototype.hasOwnProperty.call(b, key) && deepEqual(a[key], b[key])
);
}
deepEqual({ name: "Priya", age: 29 }, { age: 29, name: "Priya" }); // true
deepEqual({ a: [1, 2, 3] }, { a: [1, 2, 3] }); // true
deepEqual({ a: [1, 2, 3] }, { a: [1, 2, 4] }); // falseProducing an Actual Diff (Not Just true/false)
For debugging, a boolean is not enough — you need to know exactly which keys changed. This function returns a list of differences:
function diffJson(obj1, obj2, path = '') {
const diffs = [];
const keys = new Set([...Object.keys(obj1), ...Object.keys(obj2)]);
for (const key of keys) {
const fullPath = path ? `${path}.${key}` : key;
const v1 = obj1[key];
const v2 = obj2[key];
if (!(key in obj1)) {
diffs.push({ path: fullPath, type: 'added', value: v2 });
} else if (!(key in obj2)) {
diffs.push({ path: fullPath, type: 'removed', value: v1 });
} else if (typeof v1 === 'object' && typeof v2 === 'object' && v1 !== null && v2 !== null) {
diffs.push(...diffJson(v1, v2, fullPath));
} else if (v1 !== v2) {
diffs.push({ path: fullPath, type: 'changed', from: v1, to: v2 });
}
}
return diffs;
}
const before = { id: 1, status: "pending", customer: { name: "Priya" } };
const after = { id: 1, status: "shipped", customer: { name: "Priya", vip: true } };
console.log(diffJson(before, after));
// [
// { path: 'status', type: 'changed', from: 'pending', to: 'shipped' },
// { path: 'customer.vip', type: 'added', value: true }
// ]Using JSON Diffing for API Regression Testing
- Snapshot testing — save a "known good" API response and diff future responses against it to catch unintended changes.
- Contract testing — verify a backend still returns the exact shape a frontend expects after a refactor.
- Migration verification — diff responses from an old and new version of an endpoint to confirm behavior parity.
- Webhook debugging — compare the payload your code expects against what a third-party service actually sends.
Libraries That Do This for You
- lodash.isEqual — battle-tested deep equality check for JavaScript objects.
- fast-deep-equal — a minimal, fast alternative for hot code paths.
- deep-diff (npm) — returns a structured list of additions, deletions, and edits, similar to the custom function above.
- jest's toEqual matcher — built-in deep equality for test assertions in Jest.
- DeepDiff / jsondiffpatch — libraries built specifically for visualizing and patching JSON diffs.
Frequently Asked Questions
JSON diffing is the process of comparing two JSON objects or documents to find what was added, removed, or changed between them. It is commonly used to detect changes in API responses, configuration files, and test snapshots.
Only if both objects have keys in the exact same order, since JSON.stringify preserves insertion order. For reliable deep equality regardless of key order, use a recursive comparison function or a library like lodash isEqual or fast-deep-equal.
Yes. Dev Brains AI JSON Formatter pretty-prints two JSON payloads with consistent indentation, making manual or side-by-side diffing far easier.