2026-06-02
If you've ever written $.foo.bar[0] in JSONPath, used JSON Patch to modify a document, or seen a cryptic "$ref": "#/components/schemas/User" in an OpenAPI spec, you've brushed up against JSON Pointer. RFC 6901 is a tiny specification — barely seven pages — that defines a string syntax for identifying a specific value within a JSON document. It is one of those quiet plumbing standards that quietly underpins an enormous amount of modern tooling.
The problem. JSON documents are trees. Once you have one, how do you unambiguously point to a node inside it? You might say "the third element of the items array inside order." But protocols need a machine-readable form. XML solved this long ago with XPath, a rich query language. The JSON community wanted something far simpler — no predicates, no functions, no axes — just a fragment identifier that names exactly one location.
The design. A JSON Pointer is a Unicode string of zero or more reference tokens, each prefixed by /. Evaluation starts at the document root and walks down. Given:
"" → the whole document"/foo" → the value at key foo"/foo/0" → the first element if foo is an array"/" → the value at the empty-string key (yes, JSON allows that)"/a~1b" → the value at key a/b"/m~0n" → the value at key m~nThat last pair is the spec's one piece of cleverness. Because / is the separator and ~ is the escape character, they have to be encoded inside a token: ~1 for / and ~0 for ~. The order matters — you must replace ~1 before ~0, or you'd corrupt a key like ~1. Implementers get this wrong constantly.
Array indices are decimal integers with no leading zeros, plus a special token - meaning "the nonexistent element just past the end." That's not useful for retrieval, but it's vital for JSON Patch (RFC 6902), where you might want to append to an array.
URI fragments. Section 6 defines how to embed a pointer in a URI fragment, e.g. http://example.com/schema.json#/definitions/Address. This is the form JSON Schema and OpenAPI bake into their $ref mechanism. The fragment must be percent-encoded, so a pointer with non-ASCII characters or reserved URI characters gets two layers of escaping. This is another quiet source of bugs.
Why it matters today. JSON Pointer is the addressing layer for an entire ecosystem:
$ref to compose and reuse schemas.$ref mechanism — every modern API spec is glued together by JSON Pointers.kubectl patch and many CRDT-flavored sync engines.The interesting omission. JSON Pointer deliberately can not express "all elements of an array," "every object with property X," or any kind of wildcard. That's what JSONPath (and later, the standardized RFC 9535) is for. RFC 6901 picked unambiguous, single-target identification as its entire job — and by refusing to do more, it became universally implementable in about fifty lines of code in any language. Mark Nottingham, one of the editors, has noted that the spec's brevity was the point: a thing this fundamental needed to be impossible to get wrong at the design level, even if implementers still find ways at the escaping level.
