Monstrously fast TypeScript library for generating JSON Patch (RFC 6902) diffs
ARCHIVED β’ RFC 6902 compliant β’ Type-safe β’ Zero dependencies β’ Blazing fast
Installation β’ Quick Start β’ API β’ Benchmarks
This project is archived and no longer actively maintained.
Recommended alternative: Use @sylphx/craft instead, which provides comprehensive immutable state management with JSON Patch support built-in.
A high-performance TypeScript library for generating JSON Patch operations (RFC 6902) by comparing two JSON objects. Designed to be significantly faster than existing libraries, especially for large or complex objects.
The Problem:
Traditional JSON diff libraries:
- Slow for large objects β
- Heavy dependencies β
- Complex APIs β
- Limited TypeScript support β
The Solution:
zen-json-patch:
- Optimized diff algorithm β
- Zero runtime dependencies β
- Simple, intuitive API β
- Full TypeScript type safety β
Result: Fast, reliable JSON diffing for modern applications.
| Feature | Description | Benefit |
|---|---|---|
| Optimized algorithm | Efficient recursive comparison | Fast even for large objects |
| Smart object handling | Set-based key lookups | O(1) key existence checks |
| Early exits | Strict equality checks first | Skip unnecessary comparisons |
| Zero dependencies | Pure TypeScript | Minimal bundle size |
- RFC 6902 compliant - Generates standard JSON Patch operations
- Type-safe - Full TypeScript support with strict types
- Tested - Comprehensive test suite with edge cases
- Reliable - Handles nested objects, arrays, null, and primitives
# npm
npm install zen-json-patch
# yarn
yarn add zen-json-patch
# pnpm
pnpm add zen-json-patch
# bun
bun add zen-json-patchimport { diff } from 'zen-json-patch';
const obj1 = { a: 1, b: "hello", c: true };
const obj2 = { a: 2, b: "hello", d: false };
const operations = diff(obj1, obj2);
console.log(operations);
// Output:
// [
// { op: 'replace', path: '/a', value: 2 },
// { op: 'remove', path: '/c' },
// { op: 'add', path: '/d', value: false }
// ]const before = {
user: {
name: "Alice",
age: 30,
address: { city: "NYC" }
}
};
const after = {
user: {
name: "Alice",
age: 31,
address: { city: "SF", zip: "94102" }
}
};
const patch = diff(before, after);
// [
// { op: 'replace', path: '/user/age', value: 31 },
// { op: 'replace', path: '/user/address/city', value: 'SF' },
// { op: 'add', path: '/user/address/zip', value: '94102' }
// ]const arr1 = { items: [1, 2, 3] };
const arr2 = { items: [1, 3, 4] };
const patch = diff(arr1, arr2);
// [
// { op: 'replace', path: '/items/1', value: 3 },
// { op: 'replace', path: '/items/2', value: 4 }
// ]const obj = { a: 1, b: 2 };
const patch = diff(obj, obj);
// [] (empty - no changes)Compares two JSON-compatible objects and generates an array of JSON Patch operations.
Parameters:
obj1(any) - The source objectobj2(any) - The target object
Returns: Operation[] - Array of JSON Patch operations
Operations Generated:
add- New property addedremove- Property removedreplace- Property value changed
Example:
const operations = diff(
{ name: "Alice", age: 30 },
{ name: "Bob", age: 30 }
);
// [{ op: 'replace', path: '/name', value: 'Bob' }]type Operation =
| { op: 'add', path: string, value: any }
| { op: 'remove', path: string }
| { op: 'replace', path: string, value: any }
// move and copy operations not yet implementedPaths use JSON Pointer syntax (RFC 6901):
'/' // Root
'/a' // Property 'a'
'/a/b' // Nested property
'/items/0' // Array index 0
'/a~0b' // Property 'a~b' (escaped tilde)
'/a~1b' // Property 'a/b' (escaped slash)Benchmarked against popular JSON diff libraries:
| Library | Simple Objects | Nested Objects | Large Objects (1000 keys) |
|---|---|---|---|
| zen-json-patch | β‘ Fast | β‘ Fast | β‘ Fast |
| fast-json-patch | β Good | β Good | |
| just-diff | β Good | ||
| fast-json-diff |
Run benchmarks:
npm run benchnpm run sizeZero runtime dependencies = smaller bundle size.
- Objects - Nested object comparison
- Arrays - Element-wise comparison
- Primitives - Numbers, strings, booleans, null
- Operations -
add,remove,replace
-
Array diffing - Currently uses naive element-wise comparison
- Correct but not optimized for large insertions/deletions
- No detection of element moves
- Planned: Myers diff algorithm for better array performance
-
Operations -
moveandcopyoperations not yet generated- Could be added as optimizations in future versions
// Track changes in application state
const oldState = store.getState();
// ... state updates ...
const newState = store.getState();
const changes = diff(oldState, newState);
// Send only changes to server or apply to other instances// Efficient incremental updates
const cached = cache.get('user/123');
const fresh = await api.get('user/123');
const delta = diff(cached, fresh);
if (delta.length > 0) {
cache.update('user/123', delta);
}// Track document changes
const v1 = { title: "Doc", content: "..." };
const v2 = { title: "Document", content: "...", author: "Alice" };
const changelog = diff(v1, v2);
// Store changelog for history/undo// Minimize data transfer
const localData = getLocalData();
const remoteData = fetchRemoteData();
const changes = diff(localData, remoteData);
if (changes.length < remoteData.size * 0.1) {
// Apply patch (smaller than full data)
applyPatch(localData, changes);
} else {
// Replace entirely
replaceData(remoteData);
}1. Strict equality check
ββ Same reference β No changes
ββ Different β Continue
2. Type comparison
ββ Different types β Replace
ββ Same type β Continue
3. Object type check
ββ Arrays β Compare elements
ββ Objects β Compare properties
4. Object comparison
ββ Iterate obj1 keys
β ββ Missing in obj2 β Remove
β ββ Present β Recurse
ββ Iterate remaining obj2 keys β Add
5. Array comparison (naive)
ββ Compare index by index β Replace if different
diff(
{ a: 1, b: { c: 2 } },
{ a: 1, b: { c: 3 }, d: 4 }
)
// Step 1: Root is object, recurse
// Step 2: Check 'a' β Same (1 === 1), skip
// Step 3: Check 'b' β Object, recurse
// Step 3a: Check 'c' β Different (2 !== 3)
// Operation: { op: 'replace', path: '/b/c', value: 3 }
// Step 4: Key 'd' in obj2 only
// Operation: { op: 'add', path: '/d', value: 4 }
// Result:
// [
// { op: 'replace', path: '/b/c', value: 3 },
// { op: 'add', path: '/d', value: 4 }
// ]# Install dependencies
npm install
# Run tests
npm test
# Watch mode
npm run test:watch
# Run benchmarks
npm run bench
# Build
npm run build
# Check bundle size
npm run sizezen-json-patch/
βββ src/
β βββ index.ts # Main diff function
β βββ types.ts # TypeScript types
β βββ arrayDiff.ts # Array comparison
β βββ path.ts # JSON Pointer utilities
β βββ *.spec.ts # Test files
β βββ rfc6902.spec.ts # RFC compliance tests
βββ bench/
β βββ object-diff.bench.ts
β βββ array-diff.bench.ts
βββ package.json
βββ tsconfig.json
Comprehensive test suite covering:
- β Simple objects
- β Nested objects
- β Arrays
- β Primitives
- β Edge cases (null, undefined, circular refs)
- β RFC 6902 compliance
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true
}
}Uses tsup for fast, optimized builds:
tsup src/index.ts --format esm,cjs --minify --sourcemap --dtsOutput:
dist/index.js- CommonJSdist/index.mjs- ES Modulesdist/index.d.ts- Type declarations
- fast-json-patch - Popular JSON Patch library
- just-diff - Lightweight diff utility
- json-diff - Visual JSON diff
- Basic object/array comparison
- RFC 6902 compliant operations
- TypeScript type safety
- Comprehensive test suite
- Benchmarking infrastructure
- Optimized array diffing - Myers diff algorithm
- Move operations - Detect moved elements
- Copy operations - Optimize duplicate values
- Patch application -
applyPatch()function - Performance improvements - Further optimizations
- Custom comparators - User-defined equality
- Ignore paths - Skip specific properties
Contributions are welcome! Please follow these guidelines:
- Open an issue - Discuss changes before implementing
- Fork the repository
- Create a feature branch -
git checkout -b feature/my-feature - Follow code standards - Run
npm run validate - Write tests - Maintain high coverage
- Submit a pull request
npm test # Run tests
npm run bench # Run benchmarks
npm run build # Build package
npm run size # Check bundle sizeMIT Β© Sylphx
Built with:
- TypeScript - Language
- Vitest - Testing framework
- tsup - Build tool
Inspired by:
- π Bug Reports
- π‘ Feature Requests
- π§ Email
Monstrously fast JSON diffing
RFC 6902 compliant β’ Type-safe β’ Zero dependencies
sylphx.com β’
@SylphxAI β’
hi@sylphx.com