Documentation
JSON Pointer (RFC 6901): The Complete Guide
Every path and from in a JSON Patch is a JSON Pointer. It is a small syntax - slash-separated segments, two escape sequences, one special array token - but it decides whether your patch hits the right value.
A JSON Pointer is a string that identifies one value inside a JSON document: segments separated by /, evaluated left to right. /users/0/name means: the key users, then array index 0, then the key name. The empty string addresses the whole document.
Anatomy of a pointer
Given this document:
Document
{
"users": [
{ "name": "Ana", "admin": true },
{ "name": "Ben", "admin": false }
]
}Each pointer below resolves to exactly one value:
Pointers
/users -> the whole array
/users/0 -> { "name": "Ana", "admin": true }
/users/0/name -> "Ana"
/users/1/admin -> false
"" -> the entire documentEvaluation is strict and left to right: each segment must exist before the next one is resolved, object keys must match exactly, and array segments must be valid indexes.
Objects and nested paths
Inside an object, a segment is a key - matched exactly, case included. Keys can contain spaces, punctuation and unicode without any special handling; only ~ and / need escaping (covered below). A segment that does not exist makes the whole pointer fail - pointers never create intermediate structure, though JSON Patch's add can create the final step of a path.
Array indexes
Inside an array, a segment is a zero-based index written in base 10 without leading zeros: /items/0 is the first element, /items/01 is invalid. One token is special: - names the position one past the last element. It is how JSON Patch appends - { "op": "add", "path": "/items/-", "value": "x" } - and it is covered in depth in JSON Patch and arrays.
The root pointer and empty keys
Two edge cases look similar but are opposites:
- The empty string
""is the root pointer: it addresses the entire document. In JSON Patch,addorreplacewith"path": ""replaces the whole document. - A single slash
"/"addresses the key that is itself an empty string at the root:{ "": "this value" }.
Escaping: ~0 and ~1
Because / separates segments and ~ starts an escape, a key that literally contains those characters must be escaped. RFC 6901 defines exactly two escapes:
Escape rules
~ becomes ~0 / becomes ~1
So a real key maps to its pointer segment like this:
Key to pointer
key "a/b" -> /a~1b key "m~n" -> /m~0n key "a/b~c" -> /a~1b~0c key "a~1b" -> /a~01b (a literal tilde-one in the key)
When you build a path from a key, escape ~ first and / second - otherwise you re-escape your own escape. When you evaluate a path, the RFC reverses the order: turn ~1 back into / first, then ~0 back into ~.
A full example. To change timeout inside the key "a/b":
Patch
[
{ "op": "replace", "path": "/a~1b/timeout", "value": 60 }
]Before
{ "a/b": { "timeout": 30 } }After
{ "a/b": { "timeout": 60 } }Note what stays unescaped: only the two characters above ever change. Dots, spaces, brackets and quotes in keys are written as-is.
Pointers inside JSON Patch
JSON Patch (RFC 6902) uses pointers in two places: path, the target of every operation, and from, the source of move and copy. Both follow the same rules on this page. You will also see pointers in HTTP API error responses and in JSON Schema, which reuses the same syntax.
RFC 6901 also defines a URI fragment form (#/users/0/name) for putting pointers in URLs, with percent-encoding on top. JSON Patch documents always use the plain string form described here.
Common mistakes
Forgetting the leading slash
"users/0/name" is not a valid pointer. Every non-empty pointer starts with /: "/users/0/name". The only pointer without one is the empty string, meaning the whole document.
Treating "/users/" and "/users" as the same thing
A trailing slash adds an empty-string segment: "/users/" addresses the key "" inside users. "/users" addresses users itself.
Escaping in the wrong order when building a path
Escape ~ as ~0 first, then / as ~1. If you escape the slash first you will re-escape the tilde you just introduced and corrupt the key.
Using JSONPath or dot notation
$.users[0].name and users.0.name are other languages. JSON Pointer only has slash-separated segments: /users/0/name.
Assuming keys are case-insensitive
/Name and /name are different pointers. Object keys must match exactly, character for character.
Reading with the "-" token
"-" names the slot after the last array element. It is valid only as the target of an add in JSON Patch - using it with remove, replace or test is an error.
Reference
The syntax is defined by RFC 6901, section 3, evaluation and the - token by section 4, and the URI fragment form by section 6. JSON Patch's use of pointers is in RFC 6902, section 4.
See an escaped pointer generated for you
Open the generator with a document whose key contains a slash - the patch it produces uses /a~1b automatically.
Generate a patch with an escaped key