Guide
JSON Patch in JavaScript
How to apply RFC 6902 JSON Patches in Node.js and the browser - with fast-json-patch, immutable alternatives, and diff generation between two documents.
Choosing a library
The most widely used implementation is fast-json-patch. It covers every RFC 6902 operation (add, remove, replace, move, copy, test) and works in Node and the browser:
npm install fast-json-patch
Applying a patch
applyPatch returns a result object whose newDocument holds the patched document. By default it mutates in place - pass false as the third argument and a cloned document is returned instead:
import { applyPatch } from 'fast-json-patch';
const doc = {
name: 'demo',
version: 1,
tags: ['a', 'b'],
};
const patch = [
{ op: 'replace', path: '/version', value: 2 },
{ op: 'add', path: '/tags/-', value: 'c' },
{ op: 'remove', path: '/name' },
];
const result = applyPatch(doc, patch, true, false);
console.log(result.newDocument);
// { version: 2, tags: ['a', 'b', 'c'] }The path /tags/- appends to the array. Paths are JSON Pointers (RFC 6901): escape ~ as ~0 and / as ~1 inside keys.
Generating a patch from two documents
compare produces the operations that turn one document into the other - the same output as the JSON Patch Generator:
import { compare } from 'fast-json-patch';
const before = { a: 1, b: { c: 2 } };
const after = { a: 1, b: { c: 3, d: 4 } };
console.log(compare(before, after));
// [
// { op: 'replace', path: '/b/c', value: 3 },
// { op: 'add', path: '/b/d', value: 4 },
// ]Guarding with the test operation
A failing test operation stops evaluation at that point. Use it as a precondition so a patch only lands on the state it was built for:
const patch = [
{ op: 'test', path: '/version', value: 1 },
{ op: 'replace', path: '/version', value: 2 },
];
try {
applyPatch(doc, patch, true);
} catch (err) {
// JsonPatchError: test failed, path missing, or type mismatch
console.error('patch rejected:', err.message);
}Common pitfalls
- Mutation surprises.
applyPatch(doc, patch)mutatesdocunless you request a clone. In React state, always use the immutable form or you will miss re-renders. - Strict test equality. A test on
1fails against'1'. JSON types must match exactly. - Array indices shift after remove. Removing index 0 renumbers everything after it. Remove from the highest index down, or guard with test operations.
- Evaluation stops on error. RFC 6902 does not guarantee rollback of earlier operations; check the library's mutation behavior before treating a patch as a transaction.
Prototype patches visually
Paste your two documents into the JSON Patch Generator to get the exact operations, or inspect changes line by line with the JSON Diff tool. Then hand the patch to applyPatch in your app or API client.
Background on the format: JSON Patch documentation and real-world examples.