API

JSON Pointer

class fast_json_pointer.JsonPointer(parts: list[str])

Primitive dataclass for RFC 6901 json pointers.

>>> JsonPointer(['~home', 'foo.txt', 'mime/type'])
JsonPointer('/~0home/foo.txt/mime~1type')
>>> JsonPointer.parse('/~0home/foo.txt/mime~1type')
JsonPointer('/~0home/foo.txt/mime~1type')
__eq__(other)

Return self==value.

__str__() str

Serialize to RFC 6901 json pointer.

classmethod parse(s: str) Self

Parse a serialized RFC 6901 json pointer.

parts: list[str]

Unescaped list of path parts.

>>> JsonPointer.parse("/data/items/0/id").parts
['data', 'items', '0', 'id']
class fast_json_pointer.RelativeJsonPointer(offset: int, pointer: fast_json_pointer.pointer.JsonPointer | None)

Primitive data class for 2020-12 draft json pointers.

>>> RelativeJsonPointer(0, JsonPointer(['data', 'items']))
RelativeJsonPointer('0/data/items')
>>> RelativeJsonPointer(0, None)
RelativeJsonPointer('0#')
__eq__(other)

Return self==value.

__str__() str

Serialize to 2020-12 draft relative json pointer.

property is_index_ref: bool
>>> RelativeJsonPointer.parse("0").is_index_ref
False
>>> RelativeJsonPointer.parse("0/").is_index_ref
False
>>> RelativeJsonPointer.parse("0#").is_index_ref
True
classmethod parse(s: str) Self

Parse a serialized 2020-12 draft relative json pointer.

property parts: list[str] | None

Unescaped list of path parts, if this isn’t an index reference.

>>> RelativeJsonPointer.parse("0/data/items/0/id").parts
['data', 'items', '0', 'id']
>>> RelativeJsonPointer.parse("0#").parts is None
True

RFC 6901 Parser

Implements json pointer parsing. See RFC 6901 Section 4 for the specification.

fast_json_pointer.rfc6901_parser.validate(pointer: str) None

Validate that a string is a well formed json pointer.

Raises:

ParseException: If json pointer is invalid.

>>> validate('') # empty string is fine, means "whole json object"
>>> validate('foo') # parts must lead with '/'
Traceback (most recent call last):
fast_json_pointer.exceptions.ParseException: ...
>>> validate('/foo~') # ~ is the escape char, can't be solo
Traceback (most recent call last):
fast_json_pointer.exceptions.ParseException: ...
>>> validate('/~2/foo') # only ~0, ~1 are valid escapes
Traceback (most recent call last):
fast_json_pointer.exceptions.ParseException: ...
fast_json_pointer.rfc6901_parser.parse(pointer: str) list[str]

Parse a json pointer into a list of unescaped path parts.

Raises:

ParseException: If json pointer is invalid.

>>> parse('') # empty string is "the whole json object"
[]
>>> parse('/') # keys can be zero-length strings
['']
>>> parse('/ //  ') # which can look funky
[' ', '', '  ']
>>> parse('/foo/m~0n/a~1b') # ~1 escapes /, ~0 escapes ~
['foo', 'm~n', 'a/b']
>>> parse('/c%d/e^f') # funky symbols are fine too!
['c%d', 'e^f']
>>> parse(r'/i\\j/g|h/k\l') # r-string avoids escaping backslashes
['i\\\\j', 'g|h', 'k\\l']
fast_json_pointer.rfc6901_parser.unparse(parts: Iterable[str]) str

Combine an iterable of unescaped path parts into a json pointer.

>>> unparse([])
''
>>> unparse([''])
'/'
>>> unparse([' ', '', '  '])
'/ //  '
>>> unparse(['foo', 'm~n', 'a/b'])
'/foo/m~0n/a~1b'
>>> unparse(['c%d', 'e^f'])
'/c%d/e^f'
>>> unparse([r'i\\j', 'g|h', r'k\l'])
'/i\\\\j/g|h/k\\l'
fast_json_pointer.rfc6901_parser.escape(part: str) str

Escape a path part.

>>> escape("foo")
'foo'
>>> escape("m~/0")
'm~0~10'
fast_json_pointer.rfc6901_parser.unescape(part: str) str

Unescape a path part.

>>> unescape("foo")
'foo'
>>> unescape("m~0~10")
'm~/0'

Relative Pointer Parser

Implements releative json pointer parsing. See 2020-12 relative json pointer draft for the (draft) specification.

fast_json_pointer.rel_parser.parse(s: str) tuple[int, list[str] | None]

Parse a relative json pointer into tuple[offset, parts | None].

If parts aren’t returned it’s due to the pointer containing a # operator at it’s tail, and thus being an “index / name of” reference.

Raises:

ParseException: If relative json pointer is invalid.

An offset by itself is valid.

>>> parse("0") # Points at self
(0, [])
>>> parse("1") # Points at parent
(1, [])
>>> parse("2") # Points at grandparent
(2, [])

Only non-negative integers are valid offsets.

>>> parse("-1")
Traceback (most recent call last):
fast_json_pointer.exceptions.ParseException: ...
>>> parse("-0") # Even negative zero
Traceback (most recent call last):
fast_json_pointer.exceptions.ParseException: ...

An offset must always be provided, an empty string isn’t valid.

>>> parse("")
Traceback (most recent call last):
fast_json_pointer.exceptions.ParseException: ...

An offset can be followed by # to imply the index or name of the referenced object should be returned, rather than it’s value.

>>> parse("0#")
(0, None)
>>> parse("2#")
(2, None)

# is also a valid character in a json pointer, there are a few ways to write relative pointers that break first-glance intuition.

>>> parse("0/#")
(0, ['#'])
>>> parse("0/#/foo")
(0, ['#', 'foo'])
>>> parse("0/foo#")
(0, ['foo#'])
>>> parse("0/foo/#")
(0, ['foo', '#'])

# without an offset is invalid.

>>> parse('#')
Traceback (most recent call last):
fast_json_pointer.exceptions.ParseException: ...

# must not be followed with a json pointer, or any other text.

>>> parse("0#/foo")
Traceback (most recent call last):
fast_json_pointer.exceptions.ParseException: ...
>>> parse("#im_not_a_pointer")
Traceback (most recent call last):
fast_json_pointer.exceptions.ParseException: ...
fast_json_pointer.rel_parser.unparse(offset: int, parts: Optional[Iterable[str]]) str

Serialize a relative json pointer.

>>> unparse(0, ["foo"])
'0/foo'
>>> unparse(0, None)
'0#'
>>> unparse(0, [])
'0'
>>> unparse(0, ['#'])
'0/#'
>>> unparse(0, ["foo#"])
'0/foo#'

Exceptions

exception fast_json_pointer.exceptions.JsonPointerException

Generic json pointer failure.

exception fast_json_pointer.exceptions.ParseException

Failure occurred while parsing a json pointer.