Skip to main content

JSON Patch

JSON Patch (RFC 6902) is a standard for describing update operations to perform on JSON-like data, where an operation is a JSON object including, at least, an op string and a path.

Use jsonpatch.apply(ops, data) to apply ops to data. The first argument must be an array of OpObjects, as per RFC 6902. The second argument is JSON-like data to apply the patch to. Data is updated in place.

danger

apply is not atomic. If a patch operation fails, data could be left in an inconsistent state. Section 5 of RFC 6902 states:

Note that the HTTP PATCH method is atomic

apply does not assume it is being used to handle HTTP PATCH requests. It is up to the caller to deep copy data before calling apply, if necessary.

import { jsonpatch } from "json-p3";

const ops = [
{ op: "add", path: "/some/foo", value: { foo: {} } },
{ op: "add", path: "/some/foo", value: { bar: [] } },
{ op: "copy", from: "/some/other", path: "/some/foo/else" },
{ op: "add", path: "/some/foo/bar/-", value: 1 },
];

const data = { some: { other: "thing" } };
jsonpatch.apply(ops, data);
console.log(data);
// { some: { other: 'thing', foo: { bar: [Array], else: 'thing' } } }

Use the JSONPatch constructor to create a patch for repeated application.

import { JSONPatch } from "json-p3";

const patch = new JSONPatch([
{ op: "add", path: "/some/foo", value: { foo: {} } },
{ op: "add", path: "/some/foo", value: { bar: [] } },
{ op: "copy", from: "/some/other", path: "/some/foo/else" },
{ op: "add", path: "/some/foo/bar/-", value: 1 },
]);

const data = { some: { other: "thing" } };
patch.apply(data);
console.log(data);
// { some: { other: 'thing', foo: { bar: [Array], else: 'thing' } } }

Builder API​

JSONPatch implements a builder interface for constructing JSON Patch documents. Each of the following methods appends an operation to the patch and returns the patch instance, so method calls can be chained.

add()​

JSONPatch.add(pointer, value) appends an add operation to the patch. pointer can be a string following RFC 6901 or an instance of JSONPointer.

import { JSONPatch } from "json-p3";

const patch = new JSONPatch().add("/some/foo", { foo: [] });
console.log(JSON.stringify(patch.toArray(), undefined, " "));
output
[
{
"op": "add",
"path": "/some/foo",
"value": {
"foo": []
}
}
]

remove()​

JSONPatch.remove(pointer) appends a remove operation to the patch. pointer can be a string following RFC 6901 or an instance of JSONPointer.

import { JSONPatch } from "json-p3";

const patch = new JSONPatch().remove("/some/foo");
console.log(JSON.stringify(patch.toArray(), undefined, " "));
output
[
{
"op": "remove",
"path": "/some/foo"
}
]

replace()​

JSONPatch.replace(pointer, value) appends a replace operation to the patch. pointer can be a string following RFC 6901 or an instance of JSONPointer.

import { JSONPatch } from "json-p3";

const patch = new JSONPatch().replace("/some/foo", [1, 2, 3]);
console.log(JSON.stringify(patch.toArray(), undefined, " "));
output
[
{
"op": "replace",
"path": "/some/foo",
"value": [1, 2, 3]
}
]

move()​

JSONPatch.move(fromPointer, toPointer) appends a move operation to the patch. fromPointer and toPointer can be a string following RFC 6901 or an instance of JSONPointer.

import { JSONPatch } from "json-p3";

const patch = new JSONPatch().move("/some/foo", "/other/bar");
console.log(JSON.stringify(patch.toArray(), undefined, " "));
output
[
{
"op": "move",
"from": "/some/foo",
"path": "/other/bar"
}
]

copy()​

JSONPatch.copy(fromPointer, toPointer) appends a copy operation to the patch. fromPointer and toPointer can be a string following RFC 6901 or an instance of JSONPointer.

import { JSONPatch } from "json-p3";

const patch = new JSONPatch().copy("/some/foo", "/other/bar");
console.log(JSON.stringify(patch.toArray(), undefined, " "));
output
[
{
"op": "copy",
"from": "/some/foo",
"path": "/other/bar"
}
]

test()​

JSONPatch.copy(pointer, value) appends a test operation to the patch. pointer can be a string following RFC 6901 or an instance of JSONPointer.

import { JSONPatch } from "json-p3";

const patch = new JSONPatch().test("/some/foo", "hello");
console.log(JSON.stringify(patch.toArray(), undefined, " "));
output
[
{
"op": "test",
"path": "/some/foo",
"value": "hello"
}
]