RCF 6901 implementation of JSON Pointer
npm install @swaggerexpert/json-pointer






@swaggerexpert/json-pointer is a parser, validator, evaluator, compiler and representer for RFC 6901 JavaScript Object Notation (JSON) Pointer.
![]() | Get professionally supported @swaggerexpert/json-pointer with Tidelift Subscription. |
- Getting started
- Installation
- Usage
- Parsing
- Translators
- CST
- AST
- XML
- Statistics
- Tracing
- Validation
- Escaping
- Evaluation
- Strict Arrays
- Strict Objects
- Evaluation Realms
- JSON
- Map/Set
- Custom
- Composing Realms
- Evaluation Diagnostics
- Evaluation Tracing
- Compilation
- Representation
- JSON String
- URI Fragment Identifier
- Errors
- Grammar
- More about JSON Pointer
- License
You can install @swaggerexpert/json-pointer using npm:
``sh`
$ npm install @swaggerexpert/json-pointer
---
Include following script tag into your HTML file:
`html`
Global variable JSONPointer will be available in the browser matching interface of @swaggerexpert/json-pointer npm package.json-pointer.browser.min.js is UMD minified build artifact.json-pointer.browser.js
There is also unminified artifact, suitable for debugging.
---
Include following script tag into your HTML file (ESM mode):
`html`JSONPointer
Local variable will be available in scope of the
`
Global variable JSONPointer will be available in the browser matching interface of @swaggerexpert/json-pointer npm package.json-pointer.browser.min.js is UMD minified build artifact.json-pointer.browser.js
There is also unminified artifact, suitable for debugging.
@swaggerexpert/json-pointer currently supports parsing, validation ,evaluation, compilation and representation.
Both parser and validator are based on a superset of ABNF (SABNF)
and use apg-lite parser generator.
#### Parsing
Parsing a JSON Pointer is as simple as importing the parse function and calling it.
`js
import { parse } from '@swaggerexpert/json-parse';
const parseResult = parse('/foo/bar');
`
parseResult variable has the following shape:
``
{
result:
tree:
stats:
trace:
}
TypeScript typings are available for all fields attached to parse result object returned by the parse function.
##### Translators
@swaggerexpert/json-pointer provides several translators to convert the parse result into different tree representations.
###### CST translator
Concrete Syntax Tree (Parse tree) representation is available on parse result
when instance of CSTTranslator is provided via a translator option to the parse function.
CST is suitable to be consumed by other tools like IDEs, editors, etc...
`js
import { parse, CSTTranslator } from '@swaggerexpert/json-pointer';
const { tree: CST } = parse('/foo/bar', { translator: new CSTTranslator() });
`
CST tree has a shape documented by TypeScript typings (CSTTree).
###### AST translator
Default translator. Abstract Syntax Tree representation is available on parse result
by default or when instance of ASTTranslator is provided via a translator option to the parse function.
AST is suitable to be consumed by implementations that need to analyze the structure of the JSON Pointer
or for building a custom JSON Pointer evaluation engine.
AST of the parsed JSON Pointer is a list of unescaped reference tokens.
`js
import { parse } from '@swaggerexpert/json-pointer';
const { tree: AST } = parse('/foo/bar'); // AST = ['foo', 'bar']
`
or
`js
import { parse, ASTTranslator } from '@swaggerexpert/json-poiner';
const { tree: AST } = parse('/foo/bar', { translator: new ASTTranslator() }); // AST = ['foo', 'bar']
`
###### XML translator
`js
import { parse, XMLTranslator } from '@swaggerexpert/json-pointer';
const { tree: XML } = parse('$.store.book[0].title', { translator: new XMLTranslator() });
`
##### Statistics
parse function returns additional statistical information about the parsing process.stats
Collection of the statistics can be enabled by setting option to true.
`js
import { parse } from '@swaggerexpert/json-pointer';
const { stats } = parse('/foo/bar', { stats: true });
stats.displayStats(); // returns operator stats
stats.displayHits(); // returns rules grouped by hit count
`
##### Tracing
parse function returns additional tracing information about the parsing process.trace
Tracing can be enabled by setting option to true. Tracing is essential
for debugging failed matches or analyzing rule execution flow.
`js
import { parse } from '@swaggerexpert/json-pointer';
const { result, trace } = parse('1', { trace: true });
result.success; // returns false
trace.displayTrace(); // returns trace information
trace.inferExpectations(); // returns parser expectations
`
By combining information from result and trace, it is possible to analyze the parsing process in detail'Invalid JSON Pointer: "1". Syntax error at position 0, expected "/"'
and generate a messages like this: . Please see this
test file for more information how to achieve that.
#### Validation
Validating a JSON Pointer is as simple as importing one of the validation functions and calling it.
`js
import {
testJSONPointer,
testReferenceToken,
testArrayLocation,
testArrayIndex,
testArrayDash
} from '@swaggerexpert/json-pointer';
testJSONPointer('/foo/bar'); // => true
testReferenceToken('foo'); // => true
testArrayLocation('0'); // => true
testArrayLocation('-'); // => true
testArrayIndex('0'); // => true
testArrayDash('-'); // => true
`
#### Escaping
[comment]: <> (SPDX-FileCopyrightText: Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved.)
[comment]: <> (SPDX-License-Identifier: BSD-2-Clause)
Because the characters '~' (%x7E) and '/' (%x2F) have special'~'
meanings in JSON Pointer, needs to be encoded as '~0' and '/''~1'
needs to be encoded as when these characters appear in a
reference token.
`js
import { escape } from '@swaggerexpert/json-pointer';
escape('~foo'); // => '~0foo'
escape('/foo'); // => '~1foo'
`
[comment]: <> (SPDX-FileCopyrightText: Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved.)
[comment]: <> (SPDX-License-Identifier: BSD-2-Clause)
Unescape is performed by first transforming any
occurrence of the sequence '~1' to '/', and then transforming any'~0'
occurrence of the sequence to '~'. By performing the'~01'
substitutions in this order, this library avoids the error of
turning first into '~1' and then into '/', which would be'~01'
incorrect (the string correctly becomes '~1' after transformation).
`js
import { unescape } from '@swaggerexpert/json-pointer';
unescape('~0foo'); // => '~foo'
unescape('~1foo'); // => '/foo'
`
#### Evaluation
[comment]: <> (SPDX-FileCopyrightText: Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved.)
[comment]: <> (SPDX-License-Identifier: BSD-2-Clause)
Evaluation of a JSON Pointer begins with a reference to the root
value of a JSON document and completes with a reference to some value
within the document. Each reference token in the JSON Pointer is
evaluated sequentially.
`js
import { evaluate } from '@swaggerexpert/json-pointer';
const value = {
"foo": ["bar", "baz"],
"": 0,
"a/b": 1,
"c%d": 2,
"e^f": 3,
"g|h": 4,
"i\\j": 5,
"k\"l": 6,
" ": 7,
"m~n": 8
};
evaluate(value, ''); // => identical to value
evaluate(value, '/foo'); // => ["bar", "baz"]
evaluate(value, '/foo/0'); // => "bar"
evaluate(value, '/'); // => 0
evaluate(value, '/a~1b'); // => 1
evaluate(value, '/c%d'); // => 2
evaluate(value, '/e^f'); // => 3
evaluate(value, '/g|h'); // => 4
evaluate(value, '/i\\j'); // => 5
evaluate(value, '/k"l'); // => 6
evaluate(value, '/ '); // => 7
evaluate(value, '/m~0n'); // => 8
// neither object nor array
evaluate(null, '/foo'); // => throws JSONPointerTypeError
// arrays
evaluate(value, '/foo/2'); // => throws JSONPointerIndexError
evaluate(value, '/foo/-'); // => throws JSONPointerIndexError
evaluate(value, '/foo/a'); // => throws JSONPointerIndexError
// objects
evaluate(value, '/bar'); // => throws JSONPointerKeyError
`
###### Strict Arrays
[comment]: <> (SPDX-FileCopyrightText: Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved.)
[comment]: <> (SPDX-License-Identifier: BSD-2-Clause)
By default, the evaluation is strict, meaning an error condition will be raised if it fails to
resolve a concrete value for any of the JSON pointer's reference tokens. For example, if an array
is referenced with a non-numeric token, an error condition will be raised.
Note that the use of the "-" character to index an array will always
result in such an error condition because by definition it refers to
a nonexistent array element.
This spec compliant strict behavior can be disabled by setting the strictArrays option to false.
`js`
evaluate(value, '/foo/2', { strictArrays: false }); // => undefined
evaluate(value, '/foo/-', { strictArrays: false }); // => undefined
evaluate(value, '/foo/132423', { strictArrays: false }); // => undefined
###### Strict Objects
[comment]: <> (SPDX-FileCopyrightText: Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved.)
[comment]: <> (SPDX-License-Identifier: BSD-2-Clause)
By default, the evaluation is strict, meaning error condition will be raised if it fails to
resolve a concrete value for any of the JSON pointer's reference tokens. For example,
if a token references a key that is not present in an object, an error condition will be raised.
This spec compliant strict behavior can be disabled by setting the strictObjects option to false.
`js`
evaluate(value, '/bar', { strictObjects: false }); // => undefined
strictObjects options has no effect in cases where evaluation of previous
reference token failed to resolve a concrete value.
`js`
evaluate(value, '/bar/baz', { strictObjects: false }); // => throw JSONPointerTypeError
##### Evaluation Realms
An evaluation realm defines the rules for interpreting and navigating data structures in JSON Pointer evaluation.
While JSON Pointer traditionally operates on JSON objects and arrays, evaluation realms allow the evaluation to work
polymorphically with different data structures, such as Map,
Set, Immutable.js,
or even custom representations like SpecLynx ApiDOM.
Realm can be specified via the realm option in the evalute() function.
###### JSON Evaluation Realm
By default, the evaluation operates under the JSON realm, which assumes that:
- Arrays are indexed numerically.
- Objects (plain JavaScript objects) are accessed by string keys.
The default realm is represented by the JSONEvaluationRealm class.
`js
import { evaluate } from '@swaggerexpert/json-pointer';
evaluate({ a: 'b' }, '/a'); // => 'b'
`
is equivalent to:
`js
import { evaluate } from '@swaggerexpert/json-pointer';
import JSONEvaluationRealm from '@swaggerexpert/json-pointer/evaluate/realms/json';
evaluate({ a: 'b' }, '/a', { realm: new JSONEvaluationRealm() }); // => 'b'
`
###### Map/Set Evaluation Realm
The Map/Set realm extends JSON Pointer evaluation to support Map and Set instances,
allowing structured traversal and access beyond traditional JavaScript objects and arrays.
Map/Set realm is represented by the MapSetEvaluationRealm class.
`js
import { evaluate } from '@swaggerexpert/json-pointer';
import MapSetEvaluationRealm from '@swaggerexpert/json-pointer/evaluate/realms/map-set';
const map = new Map([
['a', new Set(['b', 'c'])]
]);
evaluate(map, '/a/1', { realm: new MapSetEvaluationRealm() }); // => 'c'
`
###### Custom Evaluation Realms
The evaluation is designed to support custom evaluation realms,
enabling JSON Pointer evaluation for non-standard data structures.
A valid custom evaluation realm must match the structure of the EvaluationRealm interface.
One way to create a custom realm is to extend the EvaluationRealm class and implement the required methods.
`js
import { evaluate, EvaluationRealm } from '@swaggerexpert/json-pointer';
class CustomEvaluationRealm extends EvaluationRealm {
name = 'cusotm';
isArray(node) { ... }
isObject(node) { ... }
sizeOf(node) { ... }
has(node, referenceToken) { ... }
evaluate(node, referenceToken) { ... }
}
evaluate({ a: 'b' }, '/a', { realm: new CustomEvaluationRealm() }); // => 'b'
`
Reference implementations for Minim, SpecLynx ApiDOM,
and Immutable.js are available in the contrib/realms/ directory.
These can be copied and adapted for your specific needs.
###### Composing Evaluation Realms
Evaluation realms can be composed to create complex evaluation scenarios,
allowing JSON Pointer evaluation to work across multiple data structures in a seamless manner.
By combining different realms, composite evaluation ensures that a JSON Pointer query can
resolve correctly whether the data structure is an object, array, Map, Set, or any custom type.
When composing multiple evaluation realms, the order matters. The composition is performed from left to right, meaning:
- More specific realms should be placed first (leftmost position).
- More generic realms should be placed later (rightmost position).
This ensures that specialized data structures (e.g., Map, Set, Immutable.js) take precedence over generic JavaScript objects and arrays.
`js
import { composeRealms, evaluate } from '@swaggerexpert/json-pointer';
import JSONEvaluationRealm from '@swaggerexpert/json-pointer/realms/json';
import MapSetEvaluationRealm from '@swaggerexpert/json-pointer/realms/map-set';
const compositeRealm = composeRealms(new MapSetEvaluationRealm(), new JSONEvaluationRealm());
const structure = [
{
a: new Map([
['b', new Set(['c', 'd'])]
]),
},
];
evaluate(structure, '/0/a/b/1', { realm : compositeRealm }); // => 'd'
`
##### Evaluation Diagnostics
@swaggerexpert/json-pointer provides rich diagnostic information to help identify and resolve issues during JSON Pointer evaluation.
When evaluation fails, the library throws errors from a well-defined hierarchy — all extending from JSONPointerEvaluateError.
These errors carry detailed diagnostic metadata describing what failed, where it failed, and why.
Each error includes following fields:
- jsonPointer – the full pointer being evaluatedreferenceToken
- – the token that caused the failurereferenceTokenPosition
- – the index of that token within the pointerreferenceTokens
- – the full list of parsed reference tokenscurrentValue
- – the value being evaluated at the point of failurerealm
- – the name of the evaluation realm (e.g., "json")
##### Evaluation Tracing
@swaggerexpert/json-pointer package supports evaluation tracing, allowing you to inspect each step of JSON Pointer evaluation in detail.
This is especially useful for debugging, error reporting, visualization tools, or implementing custom behavior like fallbacks and partial evaluations.
How it works?
To enable tracing, provide an empty trace object when calling evaluate.
trace object is populated with detailed information about each step of the evaluation process:
Tracing successful evaluation:
`js
import { evaluate } from '@swaggerexpert/json-pointer';
const trace = {};
evaluate({ a: 'b' }, '/a', { trace });
`
`js`
// trace
{
steps: [
{
referenceToken: 'a',
referenceTokenPosition: 0,
input: { a: 'b' },
inputType: 'object',
output: 'b',
success: true
}
],
failed: false,
failedAt: -1,
message: 'JSON Pointer "/a" successfully evaluated against the provided value',
context: {
jsonPointer: '/a',
referenceTokens: [ 'a' ],
strictArrays: true,
strictObjects: true,
realm: 'json',
value: { a: 'b' }
}
}
Tracing failed evaluation:
`js
import { evaluate } from '@swaggerexpert/json-pointer';
const trace = {};
try {
evaluate({ a: 'b' }, '/c', { trace });
} catch {}
`
`js`
// trace
{
steps: [
{
referenceToken: 'c',
referenceTokenPosition: 0,
input: { a: 'b' },
inputType: 'object',
output: undefined,
success: false,
reason: 'Invalid object key "c" at position 0 in "/c": key not found in object'
}
],
failed: true,
failedAt: 0,
message: 'Invalid object key "c" at position 0 in "/c": key not found in object',
context: {
jsonPointer: '/c',
referenceTokens: [ 'c' ],
strictArrays: true,
strictObjects: true,
realm: 'json',
value: { a: 'b' }
}
}
trace option can additionally be set to true to enable parse tracing without providing an empty object.trace
When parsing of the JSON Pointer fails during evaluation, the generated error will contain additional information explaining the failure.
This is the default behavior of the option. You can also set trace to false to disable tracing entirely.
#### Compilation
Compilation is the process of transforming a list of unescaped reference tokens into a JSON Pointer.
Reference tokens are escaped before compiled into a JSON Pointer.
`js
import { compile } from '@swaggerexpert/json-pointer';
compile(['~foo', 'bar']); // => '/~0foo/bar'
`
#### Representation
##### JSON String
[comment]: <> (SPDX-FileCopyrightText: Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved.)
[comment]: <> (SPDX-License-Identifier: BSD-2-Clause)
A JSON Pointer can be represented in a JSON string value. Per
RFC4627, Section 2.5, all instances of quotation mark '"' (%x22),'\'
reverse solidus (%x5C), and control (%x00-1F) characters MUST be
escaped.
`js
import { JSONString } from '@swaggerexpert/json-pointer';
JSONString.to('/foo"bar'); // => '"/foo\\"bar"'
JSONString.from('"/foo\\"bar"'); // => '/foo"bar'
`
##### URI Fragment Identifier
[comment]: <> (SPDX-FileCopyrightText: Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved.)
[comment]: <> (SPDX-License-Identifier: BSD-2-Clause)
A JSON Pointer can be represented in a URI fragment identifier by
encoding it into octets using UTF-8 RFC3629, while percent-encoding
those characters not allowed by the fragment rule in RFC3986.
`js
import { URIFragmentIdentifier } from '@swaggerexpert/json-pointer';
URIFragmentIdentifier.to('/foo"bar'); // => '#/foo%22bar'
URIFragmentIdentifier.from('#/foo%22bar'); // => '/foo"bar'
URIFragmentIdentifier.fromURIReference('https://swaggerexpert.com/path#/foo%22bar'); // => '/foo"bar'
`
#### Errors
@swaggerexpert/json-pointer provides a structured error class hierarchy,
enabling precise error handling across JSON Pointer operations, including parsing, evaluation, compilation and validation.
`js`
import {
JSONPointerError,
JSONPointerParseError,
JSONPointerCompileError,
JSONPointerEvaluateError,
JSONPointerTypeError,
JSONPointerKeyError,
JSONPointerIndexError
} from '@swaggerexpert/json-pointer';
JSONPointerError is the base class for all JSON Pointer errors.
#### Grammar
New grammar instance can be created in following way:
`js
import { Grammar } from '@swaggerexpert/json-pointer';
const grammar = new Grammar();
`
To obtain original ABNF (SABNF) grammar as a string:
`js
import { Grammar } from '@swaggerexpert/json-pointer';
const grammar = new Grammar();
grammar.toString();
// or
String(grammar);
`
JSON Pointer is defined by the following ABNF syntax
[comment]: <> (SPDX-FileCopyrightText: Copyright (c) 2013 IETF Trust and the persons identified as the document authors. All rights reserved.)
[comment]: <> (SPDX-License-Identifier: BSD-2-Clause)
`abnf
; JavaScript Object Notation (JSON) Pointer ABNF syntax
; https://datatracker.ietf.org/doc/html/rfc6901
json-pointer = *( slash reference-token ) ; MODIFICATION: surrogate text rule used
reference-token = *( unescaped / escaped )
unescaped = %x00-2E / %x30-7D / %x7F-10FFFF
; %x2F ('/') and %x7E ('~') are excluded from 'unescaped'
escaped = "~" ( "0" / "1" )
; representing '~' and '/', respectively
; https://datatracker.ietf.org/doc/html/rfc6901#section-4
array-location = array-index / array-dash
array-index = %x30 / ( %x31-39 *(%x30-39) )
; "0", or digits without a leading "0"
array-dash = "-"
; Surrogate named rules
slash = "/"
`
@swaggerexpert/json-pointer is licensed under Apache 2.0 license.@swaggerexpert/json-pointer` comes with an explicit NOTICE file
containing additional legal notices and information.