CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-jsonpath-rw

A robust and significantly extended implementation of JSONPath for Python, with a clear AST for metaprogramming.

Pending
Overview
Eval results
Files

context.mddocs/

Data Context Management

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.

Capabilities

DatumInContext Class

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
        """

AutoIdForDatum Class

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
        """

Usage Examples

Basic Context Usage

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')

Automatic ID Field Generation

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]']

Context Chain Navigation

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.name

Building Context Manually

from 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].name

Extending Context Chains

from 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 Configuration

Auto ID Field

# Global variable controlling automatic ID field generation
auto_id_field = None  # Default: disabled

When 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 identifiers

Error Handling

Context operations are generally safe, but some scenarios can cause issues:

  • Missing Parent Context: Accessing parent operator when no parent exists will crash
  • Invalid Context Chains: Malformed context chains may produce unexpected full_path results
  • Type Compatibility: Some operations expect specific data types in the context chain

Install with Tessl CLI

npx tessl i tessl/pypi-jsonpath-rw

docs

cli.md

context.md

expressions.md

index.md

parsing.md

tile.json