jsoncmp
Version:
Fast and type-safe deep comparison for JSON-compatible data.
199 lines (145 loc) • 7.14 kB
Markdown
[](https://www.npmjs.com/package/jsoncmp)
[](https://jsr.io/@observ33r/jsoncmp)
[](https://jsr.io/@observ33r/jsoncmp/score)
[](https://bundlephobia.com/package/jsoncmp)
[](https://github.com/observ33r/jsoncmp/blob/main/LICENSE)
[](https://www.paypal.com/donate/?hosted_button_id=PPPN7F3VXXE8W)
# jsoncmp
Blazingly fast and type-safe deep comparison for JSON-compatible data, optimized for modern runtime environments.
## Features
- **High Performance**
Outperforms popular libraries like `fast-equals`, `dequal/lite`, `lodash.isEqual`, `node.isDeepStrictEqual` and even comparisons using the native `JSON.stringify` method.
- **Engine-Aware Design**
Tailored execution paths for V8 and JSC based runtimes to maximize performance.
- **Type-Safe**
Fully typed with TypeScript declarations.
## Installation
```bash
# npm / node
npm install jsoncmp
# jsr / deno
deno add @observ33r/jsoncmp
# bun
bun install jsoncmp
```
## Usage
```ts
import jsoncmp from 'jsoncmp';
export type JSONCmpValue =
| number
| string
| boolean
| null
| JSONCmpArray
| JSONCmpObject;
export type JSONCmpArray = JSONCmpValue[];
export interface JSONCmpObject {
[key: string]:
| JSONCmpValue
| undefined
}
/**
* Compares two JSON-compatible values for deep structural equality.
*
* This function supports only the following value types:
* number, string, boolean, null, arrays, and plain objects (no functions, symbols, etc.).
*
* The comparison is optimized based on runtime heuristics for V8 and JavaScriptCore.
*
* @param target - The first value to compare
* @param source - The second value to compare
* @returns `true` if both values are structural identical, otherwise `false`
*/
function jsoncmp(target: JSONCmpValue, source: JSONCmpValue): boolean
```
## Example
```ts
import jsoncmp from 'jsoncmp';
const target = JSON.parse('{ "a": 1, "b": ['2', null, false] }');
const source = JSON.parse('{ "a": 1, "b": ['2', null, false] }');
console.log(jsoncmp(target, source)); //true
```
## Benchmark
**Big JSON Object (~1.2 MiB, deeply nested)**
| Library | Time | Relative Speed |
| :--- | :--- | :--- |
| jsoncmp | 341.63 µs | 1.00x (baseline) |
| fast-equals | 1.38 ms | 4.05x slower |
| dequal/lite | 1.45 ms | 4.24x slower |
| node.isDeepStrictEqual | 2.48 ms | 7.25x slower |
| JSON.stringify | 3.84 ms | 11.24x slower |
| lodash.isEqual | 6.24 ms | 18.27x slower |
<details>
<summary>Full benchmark result with hardware counters</summary>
```console
clk: ~3.67 GHz
cpu: AMD Ryzen 5 3600 6-Core Processor
runtime: node 24.4.1 (x64-linux)
benchmark avg (min … max) p75 / p99 (min … top 1%)
------------------------------------------- -------------------------------
• Big JSON Object (~1.2 MiB, deeply nested)
------------------------------------------- -------------------------------
jsoncmp 341.63 µs/iter 339.20 µs █
(327.78 µs … 604.35 µs) 534.00 µs █
(382.48 kb … 1.23 mb) 967.89 kb ██▃▂▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
3.12 ipc ( 87.01% cache) 3.20k branch misses
1.39M cycles 4.34M instructions 91.63k c-refs 11.90k c-misses
fast-equals 1.38 ms/iter 1.44 ms █
(1.26 ms … 1.83 ms) 1.74 ms ██▆ ▂▃
(763.16 kb … 1.11 mb) 968.27 kb ███▅██▂▃▄▄▃▂▂▂▅▇▃▂▂▂▁
2.69 ipc ( 87.40% cache) 13.65k branch misses
5.33M cycles 14.30M instructions 130.47k c-refs 16.44k c-misses
dequal/lite 1.45 ms/iter 1.46 ms █
(1.41 ms … 1.80 ms) 1.68 ms █▂
(204.09 kb … 486.02 kb) 484.41 kb ████▇▄▂▃▂▂▂▁▁▁▁▂▁▁▁▁▁
2.62 ipc ( 88.67% cache) 12.31k branch misses
5.58M cycles 14.60M instructions 108.22k c-refs 12.26k c-misses
lodash.isEqual 6.24 ms/iter 6.38 ms ▅ ▄█
(5.90 ms … 7.82 ms) 6.95 ms █▇▇ ██▃
( 3.08 mb … 5.50 mb) 4.23 mb ▅███▇▅▄▇███▆▄▂▄▁▁▁▁▁▂
2.49 ipc ( 97.72% cache) 33.35k branch misses
24.77M cycles 61.79M instructions 1.48M c-refs 33.85k c-misses
JSON.stringify 3.84 ms/iter 3.83 ms ██
(3.56 ms … 8.55 ms) 5.48 ms ██
( 1.39 mb … 1.40 mb) 1.39 mb ██▇█▄▃▄▄▂▁▂▃▁▁▁▁▁▁▁▁▁
2.68 ipc ( 89.46% cache) 51.52k branch misses
12.81M cycles 34.38M instructions 422.39k c-refs 44.54k c-misses
node.isDeepStrictEqual 2.48 ms/iter 2.47 ms █▃
(2.42 ms … 3.47 ms) 2.96 ms ██
(376.59 kb … 1.80 mb) 1.36 mb ███▄▁▁▁▁▁▂▂▁▁▁▁▁▂▁▁▁▁
2.73 ipc ( 92.25% cache) 16.40k branch misses
9.55M cycles 26.06M instructions 187.67k c-refs 14.55k c-misses
summary
jsoncmp
4.05x faster than fast-equals
4.24x faster than dequal/lite
7.25x faster than node.isDeepStrictEqual
11.24x faster than JSON.stringify
18.27x faster than lodash.isEqual
```
</details>
---
Benchmark uses [mitata](https://github.com/evanwashere/mitata) to test performance with [big JSON object](https://github.com/observ33r/jsoncmp/blob/main/benchmark/data.ts) to reflect a realistic real-world scenario.
You can run bechmark with:
```bash
npm run benchmark
```
## Build
This package uses [rollup](https://rollupjs.org/) to generate clean and optimized ESM/CJS builds.
To build package from source code, run:
```bash
npm run build
```
This will generate the output in the `dist/` folder. Builds are handled via custom rollup config and exposed under appropriate `exports` in `package.json`.
## Testing
All tests are written in [Vitest](https://vitest.dev) with native ESM support and zero transform overhead.
You can run the full suite with:
```bash
npm test
```
## Support
If you find this project useful, you can support it with a one-time donation over [PayPal](https://www.paypal.com/donate/?hosted_button_id=PPPN7F3VXXE8W). Thank you!
## Contributing
Feel free to open issues or submit pull requests on [GitHub](https://github.com/observ33r/jsoncmp).
## License
This project is licensed under the [MIT License](LICENSE).