Developer Utilities

JSON Pointer Explorer

Resolve RFC 6901 JSON Pointers and index leaf value paths.

JSON Pointer · RFC 6901
Supports / paths and # URI fragments; ~0 means ~ and ~1 means /.
Resolved value
"Ada"
Leaf pointer index
Shows up to the first 200 leaf values.
PointerValue preview
1
"Ada"
"admin"
"editor"
2
"Lin"
"viewer"
1
false

JSON Pointer Exploration

Resolve values with RFC 6901 paths. An empty string selects the full document; / separates tokens; ~ is encoded as ~0 and / as ~1 inside keys.

Supported Forms

  • Plain pointers such as /users/0/name
  • URI fragments such as #/users/0/name
  • The leaf index shows up to 200 values and lets you select a pointer

JSON Pointer is the RFC 6901 syntax for addressing one value inside a JSON document with a slash-separated path such as /users/0/name. This explorer evaluates a pointer against a pasted document and lists the leaf paths it can index, so you can copy the exact token a JSON Patch operation, OpenAPI reference, or schema validator expects.

Two escapes, and why the order decides the answer

RFC 6901 section 3 defines exactly two escapes: ~1 for a slash and ~0 for a tilde, applied to each reference token after the pointer has been split on /. A key that literally reads ~1 is therefore written ~01, and the decoder must replace ~1 before ~0. Do it the other way round and ~01 becomes ~1, then becomes a slash: the pointer silently lands on a different node with no error. The grammar also forbids a lone trailing ~ or a ~2 sequence, so this tool rejects /a~2b outright instead of guessing, which is what surfaces pointers built by naive string concatenation.

Percent-decoding runs before the split

The fragment form of RFC 6901 section 6 prefixes the pointer with # so it can travel inside a URI, and fragment octets are percent-encoded on the way in. This tool runs decodeURIComponent over the whole fragment and only then splits on /. The consequence is that #/meta/has%2Fmore is decoded to /meta/has/more and read as two tokens rather than as the one key has/more. Slashes inside keys must go through the token escape instead, as in #/meta/has~1more. Percent-encoding is only required for characters a fragment cannot carry raw, such as spaces or non-ASCII, which is why #/a%20b and the plain /a b reach the same value.

Indexes, own keys, and what counts as a leaf

Applying a token to an array requires the RFC array-index grammar: 0 or a digit string with no leading zero, so /users/01 and /users/- both fail; - is reserved by RFC 6902 for append-at-end. An out-of-range index and a missing object key are reported as different errors, and objects are read through an own-property check, so inherited names such as constructor cannot be reached. The leaf index walks the parsed document and stops at 200 entries, emitting one pointer per scalar: strings are previewed with their quotes, numbers in re-serialized form, and null counts as a leaf, while an empty object or empty array contributes no row at all.

Worked example

Resolving a key that contains a slash

Input
Pointer /meta/has~1more against {"users":[{"name":"Ada"},{"name":"Lin"}],"meta":{"page":1,"has/more":false}}
Output
false

Splitting on / gives two tokens, meta and has~1more; the second unescapes to the single key has/more, whose value is the boolean false, printed as false rather than as a quoted string. Writing /meta/has/more fails instead, because meta has no key has. The fragment form #/meta/has~1more returns the same value.

Limits and pitfalls

  • The leaf index stops at 200 rows and each value preview is cut at 100 characters, so a large document is only partially indexed.
  • A pointer addresses exactly one location: no wildcard, no $ root, no slice, so JSONPath such as $.users[*].name fails on its first token.
  • The empty string selects the whole document while a lone / selects the member whose key is empty; neither is an alias for the root object.
  • Input is parsed with JSON.parse before any pointer is evaluated, so comments, trailing commas, NaN and single-quoted strings are rejected first.
  • Duplicate keys collapse during that parse, leaving only the last occurrence, so a pointer can never reach an earlier duplicate.

Related tools

Six ways to ask for one node, and the case each one wins

What you are actually trying to doJSON Pointer explorer on this pageWhere that job belongs instead
Pull one field out of a response you just fetchedPaste the body, type /users/0/name, and the result panel prints "Ada" — the quotes stay on because the value is re-serialised as JSON. That is the right shape for a fixture file and the wrong shape for a template that expects the bare word.When the body is already in a terminal, curl -s "$URL" | jq -r ".users[0].name" fetches and picks in one step, and -r removes the quotes this panel keeps. The panel earns its place when you have a body but no shell, or when you want to see the value before deciding.
Verify a path from a patch before applying itThe field returns the pointer string alone — no operation, no value. That string is what a patch op carries as path, escapes already in place, so you confirm the location exists once and paste the same characters into the op.Producing the patch itself is a different job: fast-json-patch or jsondiffpatch diff two documents into an op array with add, remove, test, move and copy semantics that a resolver cannot express. Only the addressing overlaps.
Trace a validator error back to the offending valueAn Ajv-style instancePath such as /users/1/roles/0 pastes in unchanged and resolves to "viewer", so the complaint and the data end up in the same view — the thing that separates a bad assertion from bad data.If the path arrived inside a patch that uses - for appending, this page rejects the token as a non-digit index. That rejection is information: the path was written for a patch consumer, not for an existing node, so fix it at the generator.
Copy a resolved subtree into source codeObjects and arrays leave the panel through JSON.stringify(value, null, 2), so a two-element array takes five lines and every nesting level adds two spaces. Readable as a snippet, wrong if what you wanted was one line in a query string.For a compact literal, run the same document through the JSON formatter with indentation off, or use jq -c ".users". The bytes survive identically; only whitespace and line breaks differ, which is also why comparing the two outputs proves nothing about the data.
Follow an OpenAPI $ref such as #/components/schemas/UserThe fragment resolves only against a document that really has components.schemas.User. Point it at a sample response and it stops at components — useful, because that failure states plainly that the pointer is aimed at the schema file, not at the payload.Cross-file $ref needs a bundler: swagger-cli bundle or a spec viewer follows references into sibling files. This page can never do it, since the textarea holds exactly one document and there is nowhere for an external target to come from.
Map the shape of a payload you have never seenThe leaf index under the result doubles as a browsing tool: each row is a pointer the field will accept, so you click down the structure instead of guessing token names. That suits a one-off glance at a document you will not query again.When the document is already a file, jq "paths(scalars)" file.json emits every leaf path with no interaction and in a form other commands can consume. Browse here once, script there when the shape repeats.

Every message this panel can show, and the token that causes it

Message in the status lineThe token that provokes itThe change that clears it
A JSON Pointer must be empty or begin with /.No token yet — the field starts with something other than / or #, as in users/0/namePut the slash back: /users/0/name. Without it the string is never split at all.
Invalid escape sequence: a~2bA token holding ~ followed by anything other than 0 or 1, or ending in a bare ~Only two escapes exist, so a literal ~2 inside a key is written ~02 and a literal ~ is ~0.
Invalid array index: firstThe current node is an array and the token is not a digit string — /users/first/name, /users/1.5, /users/+1Use the position instead: the leaf row that reads /users/0/name is a pointer the field accepts verbatim.
Array index is out of range: 2A digit string that is past the end, e.g. /users/2/name against a two-element arrayGo back one: the leaf index shows /users/1 as the last addressable element. An empty array has no index at all.
Object key does not exist: componentsThe current node is an object whose own keys do not include that token — typically a pointer lifted from another document or a schema path applied to a payloadResolve the prefix on its own (/meta) and read which keys the panel prints, then continue from a key that is actually there.
Cannot traverse through a scalar value at: lengthThe pointer keeps walking after it reached a string, number, boolean or null, as in /users/0/name/lengthStop one token earlier — /users/0/name is already the leaf. length is a property JavaScript gives strings at runtime, not a member of the JSON value.
The URI fragment contains invalid percent encoding.The field begins with # and the rest will not decode, e.g. #/a%zz or a truncated #/%E4Drop the # to skip decoding entirely — /a%zz then becomes the literal token a%zz and may well resolve.
A parser message about an unexpected character, from JSON.parseNothing in the pointer: the document was rejected before any token was read, and the leaf index is empty as wellRepair the pasted JSON. The position in the message belongs to the document text; no pointer edit can make an unparseable document resolve.

Two of these fire before any token is split — the leading-slash check and the fragment decode — so neither can name a segment. The five that inspect a token (escape, index, range, missing key, scalar) repeat the segment that failed, which is why a long pointer can fail on its seventh segment and still show only that one. All six pointer messages are localised, so a Chinese-locale page prints them in Chinese; the last row is whatever the JSON runtime emits.

Frequently Asked Questions

What standard is JSON Pointer?
RFC 6901. Slash-separated paths locate values in a JSON document: /users/0/name points at the name field of the first user; the empty string points at the whole document. It underpins JSON Patch (RFC 6902), OpenAPI $ref references, and JSON Schema.
How do I write a path for keys containing / or ~?
Per the standard, ~ is escaped as ~0 and / as ~1: the key "a/b" is addressed as /a~1b. This is the classic gotcha — without escaping, the key silently splits into two levels.
URI fragment form (#/a/0) versus plain form?
The fragment form starts with # and is used to reference part of a JSON document from a URL — OpenAPI’s "$ref": "#/components/schemas/User" is exactly this. Both forms share the same path semantics, and the tool accepts either pasted directly.

Content reviewed: