🚀 Ultra-fast, Schema-Aware JSON Patch Generation with Human-Readable Diffing
fast-json-schema-patch is a high-performance JSON patching library designed to create efficient, schema-driven patches. It intelligently understands your data structure, enabling optimized, semantic diffs, and also provides fast, human-friendly diffing tools for frontend applications. It outperforms many popular alternatives in both speed and memory usage.
🧠 Schema-Driven Diffing Unlike generic JSON diff libraries, fast-json-schema-patch leverages schema-based diff plans to:
-
⚡ Optimize array diffing using the best strategy for each case (LCS, primary key matching, etc.).
-
🧩 Generate semantic patches that align with your data’s meaning, not just its shape.
-
🎯 Compare objects intelligently by focusing only on relevant fields.
💡 Ideal for applications where the JSON structure is known and schema-driven diffs are important.
bun add fast-json-schema-patch
The core of the library is the JsonSchemaPatcher
, which uses a diff plan to optimize patch generation.
import { JsonSchemaPatcher, buildPlan } from 'fast-json-schema-patch';
// 1. Define a plan for your data structure, this needs to be done only once for a given schema
const plan = buildPlan({schema});
// 2. Instantiate the patcher with the plan
const patcher = new JsonSchemaPatcher({ plan });
// Original and modified documents
const original = {
users: [
{ id: 'user1', name: 'John Doe', status: 'active' },
{ id: 'user2', name: 'Jane Smith', status: 'inactive' },
],
};
const modified = {
users: [
{ id: 'user1', name: 'John Doe', status: 'online' }, // Changed
{ id: 'user3', name: 'Sam Ray', status: 'active' }, // Added
],
// user2 was removed
};
// 3. Generate the optimized patch
const patch = patcher.execute({original, modified});
console.log(patch);
// Output: [
// { op: "remove", path: "/users/1", oldValue: { id: 'user2', ... } },
// { op: "replace", path: "/users/0/status", value: "online", oldValue: "active" },
// { op: "add", path: "/users/-", value: { id: 'user3', ... } }
// ]
This library extends the standard JSON Patch format by adding an oldValue
field to remove
and replace
operations.
This addition makes UI rendering and state reconciliation easier but is not part of the strict RFC 6902 specification.
If you're using Zod for runtime validation, you can easily generate JSON schemas for use with fast-json-schema-patch
. Zod 4 introduced native JSON Schema conversion:
import * as z from "zod/v4";
import { JsonSchemaPatcher, buildPlan } from 'fast-json-schema-patch';
// Define your Zod schema
const userSchema = z.object({
users: z.array(z.object({
id: z.string(),
name: z.string(),
status: z.enum(['active', 'inactive', 'online'])
}))
});
// Convert Zod schema to JSON Schema
const jsonSchema = z.toJSONSchema(userSchema);
// Use the JSON schema to build a plan
const plan = buildPlan({ schema: jsonSchema });
const patcher = new JsonSchemaPatcher({ plan });
This integration makes it seamless to leverage your existing Zod schemas for optimized JSON patching. For more details on Zod's JSON Schema conversion, see the official documentation.
When you need to present diffs to users, raw JSON patches can be hard to work with. StructuredDiff helps you transform those patches into structured, human-readable diffs that are fast, memory-efficient, and frontend-friendly.
It organizes changes into:
Parent diffs: Changes outside of specific arrays.
Child diffs: Changes within a target array, keyed by unique identifiers.
This makes it easy to build side-by-side diff views or activity feeds.
import { StructuredDiff } from 'fast-json-schema-patch';
// Assuming `original`, `modified`, `patch`, and `plan` from the previous example
// 1. Instantiate the aggregator with the plan
const structuredDiff = new StructuredDiff({plan});
// 2. Execute the aggregation
const aggregatedResult = structuredDiff.execute({
original,
modified,
pathPrefix: '/users',
});
// 3. Use the result to render a UI
console.log(aggregatedResult.parentDiff); // Shows changes outside the /users array
console.log(aggregatedResult.childDiffs['user2']); // Shows user2 was removed
console.log(aggregatedResult.childDiffs['user3']); // Shows user3 was added
Creates a plan for optimizing JSON patch generation based on a JSON schema.
buildPlan(options)
options
: An object with the following properties:schema
: A JSON Schema object that describes your data structure.primaryKeyMap
(optional): A record mapping path prefixes to primary key field names.basePath
(optional): The base path for the schema traversal.
- Returns: A
Plan
object that can be used withJsonSchemaPatcher
andStructuredDiff
.
The main class for generating patches.
new JsonSchemaPatcher({ plan })
plan
: APlan
object created bybuildPlan
that describes your data structure and desired diffing strategies.
patcher.execute({original, modified})
original
: The original document to compare from.modified
: The modified document to compare to.- Returns: An array of JSON Patch operations.
The main class for creating human-readable diffs.
new StructuredDiff({plan})
plan
: APlan
object created bybuildPlan
that describes your data structure and desired diffing strategies.
structuredDiff.execute(config)
config
: AnStructuredDiffConfig
object with the following properties:pathPrefix
: The path prefix of the array to aggregate (e.g.,/users
).original
: The original document.modified
: The modified document.patches
(optional): Pre-computed patch array fromJsonSchemaPatcher
. If not provided, patches will be generated automatically.
- Returns: An
StructuredDiffResult
object containingparentDiff
and a record ofchildDiffs
.
Run benchmarks on your own data:
# Run the benchmark suite
bun run compare