When you need to point at one value inside a JSON document, or describe a change to it, two small standards do the job: JSON Pointer (RFC 6901) identifies a location, and JSON Patch (RFC 6902) describes a list of changes using those pointers. A third, JSON Merge Patch (RFC 7396), offers a simpler way to send partial updates. You'll find them in PATCH APIs, Kubernetes, JSON Schema $refs and error reports. This guide explains all three.
A JSON Pointer is a string of /-separated keys and array indexes, starting from the root:
json{ "user": { "name": "Asha", "emails": ["a@example.com", "b@example.com"], "a/b": 1, "m~n": 2 } }
| Pointer | Value |
|---|---|
"" (empty) | The whole document |
/user/name | "Asha" |
/user/emails/0 | "a@example.com" |
/user/a~1b | 1 (/ in a key is written ~1) |
/user/m~0n | 2 (~ in a key is written ~0) |
Unlike JSONPath, a pointer always identifies exactly one location. It has no wildcards, filters or recursive search. That makes it ideal for references, such as "$ref": "#/$defs/address" in JSON Schema, and for error messages that point to a field, like "field": "/items/2/quantity" in API error payloads.
A JSON Patch document is an array of operations applied in order:
json[ { "op": "replace", "path": "/user/name", "value": "Asha K." }, { "op": "add", "path": "/user/emails/-", "value": "c@example.com" }, { "op": "remove", "path": "/user/emails/0" }, { "op": "test", "path": "/user/name", "value": "Asha K." } ]
The six operations:
| op | What it does |
|---|---|
add | Adds a value. In arrays it inserts at the index, and - means "append" |
remove | Removes the value at path |
replace | Replaces an existing value (the path must exist) |
move | Moves the value at from to path |
copy | Copies the value at from to path |
test | Fails the whole patch if the value at path isn't equal to value |
A patch is atomic: if any operation fails, none of the changes apply. test operations make patches safe under concurrency. Test the current value before replacing it, so you don't overwrite someone else's change.
Over HTTP, send JSON Patch with PATCH and Content-Type: application/json-patch+json.
Merge Patch is simpler: you send a partial document, and it's merged into the target.
json{ "user": { "name": "Asha K.", "nickname": null } }
null are removed.Send it with Content-Type: application/merge-patch+json.
| JSON Patch | JSON Merge Patch | |
|---|---|---|
| Readability | Lower (a list of operations) | High (looks like the data) |
Set a field to null | Yes | No (null means remove) |
| Change one array item | Yes | No, must resend the whole array |
| Conditional updates | Yes, with test | No |
| Typical use | Precise edits, audit logs, collaborative editing | Simple partial updates from forms |
Many APIs accept Merge Patch for everyday updates and JSON Patch for advanced cases. Whichever you choose, document it and use the matching Content-Type.
Libraries can compute a patch from two versions of a document, such as fast-json-patch in JavaScript and jsonpatch in Python. That's useful for audit logs ("what changed?") and for sending minimal updates. To eyeball the difference between two documents first, use How to compare two JSON files.
Paste the document into the JSON Formatter and open the JSONPath panel. It lists every value with its path. Convert the JSONPath form $.user.emails[0] to a pointer by replacing dots and brackets with slashes: /user/emails/0.