A robust and significantly extended implementation of JSONPath for Python, with a clear AST for metaprogramming.
—
Classes that wrap data values with their path context information, enabling full path tracking, parent relationships, and automatic ID field generation. These classes maintain the relationship between matched data and their location within the original data structure.
The primary data wrapper that represents a value along with its path from a context, functioning as a zipper-like structure with parent pointers.
class DatumInContext:
"""
Represents a datum along a path from a context.
Maintains the relationship between data values and their location
within the original data structure, enabling path reconstruction
and context navigation.
"""
def __init__(self, value, path=None, context=None):
"""
Initialize a datum with context.
Parameters:
- value: The actual data value
- path: JSONPath object representing path to this datum (default: This())
- context: Parent DatumInContext or None for root
"""
@classmethod
def wrap(cls, data):
"""
Wrap data in DatumInContext if not already wrapped.
Parameters:
- data: Data to wrap (any type)
Returns:
DatumInContext: Wrapped data
"""
def in_context(self, context, path):
"""
Place this datum within another context, extending the path.
Parameters:
- context: Parent context (will be wrapped in DatumInContext)
- path: JSONPath representing path from context to this datum
Returns:
DatumInContext: New datum with extended context chain
"""
@property
def value(self):
"""
The actual data value.
Returns:
Any: The wrapped data value
"""
@property
def path(self):
"""
Path from immediate context to this datum.
Returns:
JSONPath: Path object (default: This() if no path specified)
"""
@property
def context(self):
"""
Parent context containing this datum.
Returns:
DatumInContext or None: Parent context or None for root
"""
@property
def full_path(self):
"""
Complete path from root to this datum.
Reconstructs the full path by traversing up the context chain
and composing all path segments.
Returns:
JSONPath: Complete path from root
"""
@property
def id_pseudopath(self):
"""
Path-like representation with ID fields substituted when available.
When auto_id_field is set, replaces path segments with ID values
from the data when present, creating more readable path representations.
Returns:
JSONPath: Path with ID substitutions
"""Special datum wrapper that uses the path as its value, supporting automatic ID field generation for data elements without explicit identifiers.
class AutoIdForDatum(DatumInContext):
"""
Special DatumInContext where the value is the path leading up to it.
Used for automatic ID field generation when auto_id_field is enabled.
The value becomes the string representation of the datum's id_pseudopath.
"""
def __init__(self, datum, id_field=None):
"""
Initialize auto-ID datum.
Parameters:
- datum: DatumInContext, the underlying datum
- id_field: str, ID field name (default: uses global auto_id_field)
"""
@property
def value(self):
"""
String representation of the datum's id_pseudopath.
Returns:
str: Path-based identifier string
"""
@property
def path(self):
"""
The ID field name.
Returns:
str: ID field name used for this auto-ID datum
"""
@property
def context(self):
"""
The underlying datum.
Returns:
DatumInContext: Original datum this auto-ID is based on
"""
def in_context(self, context, path):
"""
Create new AutoIdForDatum with extended context.
Parameters:
- context: Parent context
- path: JSONPath from context
Returns:
AutoIdForDatum: New auto-ID datum with extended context
"""from jsonpath_rw.jsonpath import DatumInContext, Root, Fields
# Create datum with context
datum = DatumInContext(
value=42,
path=Fields('count'),
context=DatumInContext({'count': 42, 'name': 'test'})
)
print(datum.value) # 42
print(datum.full_path) # Fields('count')import jsonpath_rw.jsonpath as jsonpath
from jsonpath_rw import parse
# Enable auto ID field
jsonpath.auto_id_field = 'id'
# Data with mixed ID presence
data = {
'users': [
{'id': 'user1', 'name': 'Alice'},
{'name': 'Bob'} # No explicit ID
]
}
# Query for auto-generated IDs
matches = parse('users[*].id').find(data)
values = [match.value for match in matches]
print(values) # ['users.user1', 'users.[1]']from jsonpath_rw import parse
data = {
'company': {
'departments': [
{'name': 'Engineering', 'head': {'name': 'Alice'}}
]
}
}
matches = parse('company.departments[0].head.name').find(data)
match = matches[0]
print(match.value) # 'Alice'
print(match.path) # Fields('name')
print(match.context.value) # {'name': 'Alice'}
print(match.full_path) # company.departments.[0].head.namefrom jsonpath_rw.jsonpath import DatumInContext, Fields, Index
# Build nested context manually
root_data = {'items': [{'name': 'test'}]}
root_datum = DatumInContext(root_data)
items_datum = DatumInContext(
value=[{'name': 'test'}],
path=Fields('items'),
context=root_datum
)
item_datum = DatumInContext(
value={'name': 'test'},
path=Index(0),
context=items_datum
)
name_datum = DatumInContext(
value='test',
path=Fields('name'),
context=item_datum
)
print(name_datum.full_path) # items.[0].namefrom jsonpath_rw.jsonpath import DatumInContext, Fields
# Create base datum
base = DatumInContext('value')
# Extend with context
extended = base.in_context(
context=DatumInContext({'nested': 'value'}),
path=Fields('nested')
)
print(extended.full_path) # nested# Global variable controlling automatic ID field generation
auto_id_field = None # Default: disabledWhen auto_id_field is set to a field name (typically 'id'), the system automatically generates path-based identifiers for data elements. This is useful for tracking objects that don't have explicit ID fields.
Example:
import jsonpath_rw.jsonpath as jsonpath
# Enable auto ID with 'id' field
jsonpath.auto_id_field = 'id'
# Now queries can access auto-generated IDs
# Objects with explicit 'id' fields use those values
# Objects without 'id' fields get path-based identifiersContext operations are generally safe, but some scenarios can cause issues:
parent operator when no parent exists will crashInstall with Tessl CLI
npx tessl i tessl/pypi-jsonpath-rw