JSON Pointer
JSON Pointer is a string that identifies one value inside a JSON
document — /items/0/name — defined in RFC 6901. It is a list of
reference tokens, each prefixed with /, applied from the root one step
at a time: an object member by key, or an array element by index.
{
"build": { "id": "8f2c", "status": "failed" },
"checks": [
{ "name": "lint", "ok": true },
{ "name": "e2e", "ok": false, "error": "timeout" }
],
"a/b": 1,
"m~n": 2,
"": 3
}
| Pointer | Value |
|---|---|
"" |
the whole document |
/build/status |
"failed" |
/checks/1 |
the e2e object |
/checks/1/ok |
false |
/a~1b |
1 (key a/b) |
/m~0n |
2 (key m~n) |
/ |
3 (the empty key) |
The rules
- The empty string is the root, not
/. A lone/means the member whose key is the empty string. - Every token is a key or an index. Against an array, the token
must be
0or a decimal number without leading zeros —/checks/01is an error, not the second element. - Two escapes, and only two.
~1is/,~0is~. Decode~1before~0: the key~1is encoded~01, and decoding in the wrong order turns it into/. -is the slot after the last element. It never resolves to a value; JSON Patch uses it to append.- No wildcards, filters or ranges. One pointer, at most one value. A pointer to a key that isn't there fails rather than returning empty.
Two spellings
The plain form above is what JSON Patch and most APIs use. The URI
fragment form prefixes # and percent-encodes anything not allowed
in a URI fragment:
/build/status plain
#/build/status fragment
#/paths/~1users~1{id} OpenAPI path "/users/{id}" — slashes escaped
#/a%20b key "a b"
That is why JSON Schema and OpenAPI references look like
"$ref": "#/$defs/address" or "#/components/schemas/User" — the part
after # is a JSON Pointer into the current document.
Where you meet it
- JSON Patch (RFC 6902) — every
pathandfromis a pointer:{ "op": "replace", "path": "/build/status", "value": "passed" }. See JSON Patch. - JSON Merge Patch doesn't use it; it sends a partial document instead.
- JSON Schema and OpenAPI —
$reffragments, and validators report the failing location as an instance pointer such as/checks/1/ok. - Problem Details and API error bodies often name the bad field with
a pointer (
"pointer": "/data/attributes/email"in JSON:API). - Libraries —
jsonpointer(Python),json-pointer(npm),nlohmann::json_pointer(C++), Jackson'sJsonNode.at()(Java).
JSON Pointer, JSONPath and jq
| JSON Pointer | JSONPath | jq | |
|---|---|---|---|
| Spec | RFC 6901 | RFC 9535 | the jq manual |
| Root | "" |
$ |
. |
| Example | /checks/1/error |
$.checks[1].error |
.checks[1].error |
| Returns | one value | a list of matches | a stream |
| Wildcards | no | [*], .. |
.[], .. |
| Filters | no | ?(@.ok == false) |
select(.ok == false) |
| Used to | address | query | query and transform |
Rule of thumb: if something has to be changed or referenced at a single location, it is a pointer. If you are looking for values, it is JSONPath or jq.
Getting a pointer without counting brackets
Comma's free JSON viewer folds a document into a tree and copies the path to any node in one click, and the JSON diff lists every change between two documents by path with an RFC 6902 patch you can apply. Both run in your browser, and either can be published as a link reviewers comment on, node by node.
Try it
Comma is free — unlimited reports, unlimited commenters, unlimited revision history.