Mastering JSON Patch: Efficiently Modify JSON with RFC 6902
This article explains the JSON Patch standard (RFC 6902), detailing its purpose, structure, supported operations, ordering and atomicity rules, and provides concrete code examples for add, remove, replace, move, copy, and test operations, including edge‑case handling.
Introduction
JSON Patch is defined by RFC 6902 and is used with the HTTP PATCH method. The MIME type for a JSON Patch document is application/json-patch+json.
Patch Document Structure
A JSON Patch is a JSON array where each element is an operation object. Every operation object must contain an op member that specifies the operation type. Depending on the operation, additional members such as path, value, or from are required.
Example HTTP request:
PATCH /my/data HTTP/1.1
Host: example.org
Content-Length: 326
Content-Type: application/json-patch+json
If-Match: "abc123"
[
{ "op": "test", "path": "/a/b/c", "value": "foo" },
{ "op": "remove", "path": "/a/b/c" },
{ "op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ] },
{ "op": "replace", "path": "/a/b/c", "value": 42 },
{ "op": "move", "from": "/a/b/c", "path": "/a/b/d" },
{ "op": "copy", "from": "/a/b/d", "path": "/a/b/e" }
]Operations are applied sequentially in the order they appear. The patch is atomic: either all operations succeed and the target document is modified, or none are applied.
The order of keys inside an operation object does not matter.
Patch objects are executed in array order.
Each operation is atomic; a failure aborts the entire patch.
Supported Operations
add remove replace move copy testadd
The add operation inserts a value at the location identified by path. The behavior depends on the target:
If path points to an array index, the value is inserted at that position, shifting subsequent elements.
If path points to a non‑existent object member, the member is created.
If path points to an existing member, the member's value is replaced.
Examples:
Add an object member:
# source data:
{ "foo": "bar" }
# JSON Patch:
[ { "op": "add", "path": "/baz", "value": "qux" } ]
# result:
{ "baz": "qux", "foo": "bar" }Add an array element at index 1:
# source data:
{ "foo": ["bar", "baz"] }
# JSON Patch:
[ { "op": "add", "path": "/foo/1", "value": "qux" } ]
# result:
{ "foo": ["bar", "qux", "baz"] }Add a nested object:
# source data:
{ "foo": "bar" }
# JSON Patch:
[ { "op": "add", "path": "/child", "value": { "grandchild": {} } } ]
# result:
{ "foo": "bar", "child": { "grandchild": {} } }remove
The remove operation deletes the value at path. When the target is an array index, the array is compacted by shifting elements left.
Examples:
Remove an object member:
# source data:
{ "baz": "qux", "foo": "bar" }
# JSON Patch:
[ { "op": "remove", "path": "/baz" } ]
# result:
{ "foo": "bar" }Remove an array element:
# source data:
{ "foo": ["bar", "qux", "baz"] }
# JSON Patch:
[ { "op": "remove", "path": "/foo/1" } ]
# result:
{ "foo": ["bar", "baz"] }replace
The replace operation substitutes the value at path with value. It is equivalent to a remove followed by an add on the same path.
# source data:
{ "baz": "qux", "foo": "bar" }
# JSON Patch:
[ { "op": "replace", "path": "/baz", "value": "boo" } ]
# result:
{ "baz": "boo", "foo": "bar" }move
The move operation transfers a value from from to path. The from location must not be a parent of path (i.e., you cannot move a value into one of its own descendants).
# source data:
{ "foo": { "waldo": "fred" }, "qux": {} }
# JSON Patch:
[ { "op": "move", "from": "/foo/waldo", "path": "/qux/thud" } ]
# result:
{ "foo": {}, "qux": { "thud": "fred" } }copy
The copy operation duplicates the value from from to path without removing the source.
test
The test operation verifies that the value at path is equal to value. Equality follows type‑specific rules (strings must match exactly, numbers must be numerically equal, arrays and objects are compared recursively, and booleans/null must be identical). If any test fails, the entire patch is rejected.
# source data:
{ "baz": "qux", "foo": ["a", 2, "c"] }
# JSON Patch (successful):
[ { "op": "test", "path": "/baz", "value": "qux" },
{ "op": "test", "path": "/foo/1", "value": 2 } ]Escaping Special Characters in Paths
In JSON Pointer syntax, the characters ~ and / must be escaped. ~ becomes ~0 and / becomes ~1.
# source data:
{ "/": 9, "~1": 10 }
# JSON Patch:
[ { "op": "test", "path": "/~01", "value": 10 } ]
# result: document unchanged because the test succeeds.Conclusion
JSON Patch enables fine‑grained updates to JSON documents without transmitting the entire payload. It is widely adopted in APIs such as Kubernetes and many other RESTful services.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
System Architect Go
Programming, architecture, application development, message queues, middleware, databases, containerization, big data, image processing, machine learning, AI, personal growth.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
