Identify specific nodes in a JSON document (RFC 6901)
—
The JsonPointer class provides an object-oriented interface for JSON pointer operations, offering advanced functionality for complex pointer manipulation, path operations, and step-by-step document navigation.
Create JsonPointer instances and perform core resolution and modification operations.
class JsonPointer:
"""A JSON Pointer that can reference parts of a JSON document"""
def __init__(self, pointer):
"""
Creates a JsonPointer from string representation.
Args:
pointer (str): JSON pointer string (must start with '/')
Raises:
JsonPointerException: If pointer format is invalid or contains invalid escapes
"""
def resolve(self, doc, default=None):
"""
Resolves the pointer against doc and returns the referenced object.
Args:
doc: JSON document to resolve against
default: Default value to return if pointer cannot be resolved.
If not provided, raises JsonPointerException on missing paths.
Returns:
The referenced object or default value
Raises:
JsonPointerException: If pointer cannot be resolved and no default provided
"""
# Alias for resolve method
get = resolve
def set(self, doc, value, inplace=True):
"""
Resolve the pointer against the doc and replace the target with value.
Args:
doc: JSON document to modify
value: Value to set at the pointer location
inplace (bool): Whether to modify document in place (default True)
Returns:
Modified document (original if inplace=True, deep copy if inplace=False)
Raises:
JsonPointerException: Cannot set root in place, or other resolution errors
"""Access the pointer's path information and internal structure.
class JsonPointer:
@property
def path(self):
"""
Returns the string representation of the pointer.
Returns:
str: The pointer path with proper escaping (e.g., '/foo/~0/~1')
"""
parts
"""
List of unescaped pointer parts (instance attribute).
Type: list of str
Description: List of unescaped path components that make up this pointer.
For example, JsonPointer("/foo/bar/0").parts == ["foo", "bar", "0"]
"""
def get_parts(self):
"""
Returns the list of the parts.
Returns:
list: List of unescaped path components (same as .parts property)
"""Perform step-by-step document navigation and partial resolution.
class JsonPointer:
def to_last(self, doc):
"""
Resolves ptr until the last step, returns (sub-doc, last-step).
Args:
doc: JSON document to navigate
Returns:
tuple: (parent_document, final_key_or_index) for the target location
"""
def walk(self, doc, part):
"""
Walks one step in doc and returns the referenced part.
Args:
doc: Current document/object
part (str): Path component to navigate (unescaped)
Returns:
Next level object or EndOfList for array "-" access.
For mappings: doc[part]
For sequences: doc[int(part)] or EndOfList(doc) if part is "-"
For duck-typed objects: doc[part] using __getitem__
Raises:
JsonPointerException: If navigation fails (missing key, invalid index, etc.)
"""
@classmethod
def get_part(cls, doc, part):
"""
Returns the next step in the correct type for accessing the document.
Args:
doc: Document to determine access type for (dict, list, or __getitem__ object)
part (str): String part to convert to appropriate type
Returns:
Properly typed key:
- str for Mapping objects (dicts)
- int for Sequence objects (lists) when part is numeric
- str "-" for Sequence objects when part is "-" (end-of-list)
- original str for duck-typed objects with __getitem__
Raises:
JsonPointerException: If part is not valid for the document type
(e.g., non-numeric index for arrays, unsupported object type)
"""Manipulate and combine pointers using containment checking and path joining.
class JsonPointer:
def contains(self, ptr):
"""
Returns True if self contains the given ptr.
Args:
ptr (JsonPointer): Pointer to check for containment
Returns:
bool: True if this pointer contains the given pointer
"""
def __contains__(self, item):
"""
Returns True if self contains the given ptr (supports 'in' operator).
Args:
item (JsonPointer): Pointer to check for containment
Returns:
bool: True if this pointer contains the given pointer
"""
def join(self, suffix):
"""
Returns a new JsonPointer with the given suffix appended to this ptr.
Args:
suffix: JsonPointer, str, or list of parts to append
Returns:
JsonPointer: New pointer with suffix appended
Raises:
JsonPointerException: If suffix is invalid
"""
def __truediv__(self, suffix):
"""
Support for '/' operator (Python 3) - same as join().
Args:
suffix: Suffix to append
Returns:
JsonPointer: New pointer with suffix appended
"""Alternative construction methods for creating pointers from parts.
class JsonPointer:
@classmethod
def from_parts(cls, parts):
"""
Constructs a JsonPointer from a list of (unescaped) paths.
Args:
parts (list): List of unescaped path components
Returns:
JsonPointer: New pointer constructed from parts
"""Support for pointer comparison, hashing, and string representation.
class JsonPointer:
def __eq__(self, other):
"""
Compares a pointer to another object.
Args:
other: Object to compare with
Returns:
bool: True if both are JsonPointers with identical parts
"""
def __hash__(self):
"""
Returns hash of the pointer for use in sets and as dict keys.
Returns:
int: Hash value based on pointer parts
"""
def __str__(self):
"""
Returns string representation of the pointer.
Returns:
str: The pointer path (same as .path property)
"""
def __repr__(self):
"""
Returns debug representation of the pointer.
Returns:
str: Debug string like 'JsonPointer("/foo/bar")'
"""from jsonpointer import JsonPointer
doc = {"users": [{"name": "Alice"}, {"name": "Bob"}]}
# Create pointer
ptr = JsonPointer("/users/0/name")
# Resolve value
name = ptr.resolve(doc) # "Alice"
# or using alias
name = ptr.get(doc) # "Alice"
# Set value
ptr.set(doc, "Alice Smith") # Modifies doc in place
# Set without modifying original
new_doc = ptr.set(doc, "Alice Johnson", inplace=False)ptr = JsonPointer("/users/0/name")
# Get path components
print(ptr.path) # "/users/0/name"
print(ptr.parts) # ["users", "0", "name"]
print(ptr.get_parts()) # ["users", "0", "name"]ptr = JsonPointer("/users/0/name")
# Navigate to parent
parent, final_key = ptr.to_last(doc)
# parent = {"name": "Alice"}, final_key = "name"
# Step-by-step navigation
current = doc
for part in ptr.parts:
current = ptr.walk(current, part)
# current = "Alice"base = JsonPointer("/users")
index = JsonPointer("/0")
field = JsonPointer("/name")
# Join pointers
user_ptr = base.join(index) # "/users/0"
name_ptr = user_ptr.join(field) # "/users/0/name"
# Using / operator (Python 3)
name_ptr2 = base / index / field # "/users/0/name"
# From parts
parts = ["users", "0", "name"]
ptr = JsonPointer.from_parts(parts) # "/users/0/name"parent = JsonPointer("/users/0")
child = JsonPointer("/users/0/name")
# Check containment
print(parent.contains(child)) # True
print(child in parent) # True (using __contains__)
# Pointer comparison
ptr1 = JsonPointer("/users/0")
ptr2 = JsonPointer("/users/0")
print(ptr1 == ptr2) # True
# Use as dict keys (hashable)
pointer_cache = {ptr1: "cached_value"}from jsonpointer import JsonPointer, JsonPointerException
try:
# Invalid pointer format
bad_ptr = JsonPointer("invalid") # Must start with '/'
except JsonPointerException as e:
print(f"Invalid pointer: {e}")
try:
# Missing path with no default
ptr = JsonPointer("/missing/path")
value = ptr.resolve(doc)
except JsonPointerException as e:
print(f"Path not found: {e}")
# Safe resolution with default
value = ptr.resolve(doc, "default_value")doc = {"items": [1, 2, 3]}
# Access array elements
ptr = JsonPointer("/items/0")
first = ptr.resolve(doc) # 1
# Access end of array (for appending)
end_ptr = JsonPointer("/items/-")
end_ref = end_ptr.resolve(doc) # EndOfList object
# Append to array using set
end_ptr.set(doc, 4) # doc becomes {"items": [1, 2, 3, 4]}Install with Tessl CLI
npx tessl i tessl/pypi-jsonpointer