JSON Deep Equality in JavaScript: Comparing Objects Correctly
JavaScript has no built-in deep equality operator. Comparing JSON objects correctly requires understanding why === fails and which alternatives work.
Why === Does Not Work for JSON Objects
The === operator compares objects by reference, not by value. Two separate objects with identical properties are not === because they are different objects in memory: { a: 1 } === { a: 1 } evaluates to false. This catches many developers off guard when writing tests or comparison logic.
For primitive JSON values (strings, numbers, booleans, null), === works correctly. The comparison problem is specific to objects and arrays, which are reference types in JavaScript. Deep equality for these types requires recursive value comparison.
The JSON.stringify Approach
A common workaround is JSON.stringify(obj1) === JSON.stringify(obj2). This works for simple cases but has subtle failure modes: key order affects the string comparison ({"a":1,"b":2} !== {"b":2,"a":1} even though they are logically equal), and non-serializable values (undefined, functions) produce identical "" for different objects.
The key-order problem can be mitigated by sorting keys before stringifying. A recursive sort function or jq's -S flag produces sorted-key JSON. But this still fails for objects with non-serializable values. For robust equality, use a dedicated deep equality library.
Reliable Deep Equality Methods
For Node.js: const { deepStrictEqual } = require("assert"); deepStrictEqual(obj1, obj2) throws AssertionError if they differ, or returns undefined if equal. This handles key order correctly (objects are equal regardless of key order) and distinguishes undefined from missing keys.
Lodash's _.isEqual(obj1, obj2) is the most widely used deep equality function in JavaScript. It handles objects, arrays, Dates, RegExp, Maps, Sets, and circular references correctly. Import just the isEqual function for minimal bundle impact: import isEqual from "lodash/isEqual".
Using a JSON Compare Tool for Development
For development-time comparison (understanding what changed between two API responses, debugging test failures), an online JSON compare tool is faster than writing comparison code. Paste the two JSON objects, get an instant diff highlighting all differences, and understand what changed.
JSON compare tools are particularly valuable when the objects are large (hundreds of fields) or deeply nested, where reading both side by side is impractical. The diff output reduces a complex comparison to a list of specific field differences.
Try JSON Compare Free Online
No sign-up required. 100% client-side — your data never leaves your browser.
Open JSON Comparearrow_forwardFrequently Asked Questions
Does structuredClone help with JSON deep equality?
structuredClone creates a deep copy but does not help with equality comparison — two structuredClone copies are still different objects. Use assert.deepStrictEqual or lodash isEqual for comparison.
Is JSON.stringify comparison reliable for test assertions?
It is fragile due to key order sensitivity and non-serializable value handling. Use a proper testing library assertion like Jest's toEqual, which performs deep equality without these issues.
Can I compare JSON objects in TypeScript with type safety?
TypeScript adds type checking to comparisons but does not change the runtime equality semantics. Use lodash isEqual with TypeScript generics or a validation library like zod for both type-safe parsing and comparison.