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

expressions.mddocs/

JSONPath Expressions

Core Abstract Syntax Tree (AST) classes representing different JSONPath operations. These classes form the building blocks of parsed JSONPath expressions and can be used to construct expressions programmatically.

Capabilities

Base JSONPath Class

Abstract base class defining the interface for all JSONPath expression types.

class JSONPath:
    """
    Base class for JSONPath abstract syntax tree nodes.
    """
    
    def find(self, data):
        """
        Find all matches for this JSONPath in the given data.
        
        Parameters:
        - data: Input data to search (dict, list, or DatumInContext)
        
        Returns:
        list[DatumInContext]: List of matching data with context
        """
    
    def update(self, data, val):
        """
        Update data at the path specified by this JSONPath.
        
        Parameters:
        - data: Input data to update
        - val: New value to set at the path
        
        Returns:
        Updated data structure
        """
    
    def child(self, child):
        """
        Create a child path with canonicalization.
        
        Parameters:
        - child: JSONPath object to use as child
        
        Returns:
        JSONPath: Composed path expression
        """
    
    def make_datum(self, value):
        """
        Create a DatumInContext from a value.
        
        Parameters:
        - value: Value to wrap (or existing DatumInContext)
        
        Returns:
        DatumInContext: Wrapped value with path context
        """

Root Expression

Represents the root object reference ($ in JSONPath syntax).

class Root(JSONPath):
    """
    JSONPath referring to the root object. Concrete syntax: '$'
    """
    
    def find(self, data):
        """
        Returns the root datum.
        
        Parameters:
        - data: Input data
        
        Returns:
        list[DatumInContext]: Single-element list with root datum
        """
    
    def update(self, data, val):
        """
        Replace entire data with new value.
        
        Parameters:
        - data: Original data
        - val: Replacement value
        
        Returns:
        val: The replacement value
        """

Current Object Expression

Represents the current datum reference (@ or `this` in JSONPath syntax).

class This(JSONPath):
    """
    JSONPath referring to the current datum. Concrete syntax: '@' or `this`
    """
    
    def find(self, datum):
        """
        Returns the current datum wrapped in context.
        
        Parameters:
        - datum: Current datum
        
        Returns:
        list[DatumInContext]: Single-element list with wrapped datum
        """
    
    def update(self, data, val):
        """
        Replace data with new value.
        
        Parameters:
        - data: Original data
        - val: Replacement value
        
        Returns:
        val: The replacement value
        """

Field Access Expression

Represents field access operations for objects.

class Fields(JSONPath):
    """
    JSONPath for field access. Supports single fields, multiple fields, and wildcards.
    """
    
    def __init__(self, *fields):
        """
        Initialize field access expression.
        
        Parameters:
        - fields: Variable number of field names (str)
                 Use '*' for all fields
        """
    
    def find(self, datum):
        """
        Find matching fields in the datum.
        
        Parameters:
        - datum: Input datum (typically dict-like)
        
        Returns:
        list[DatumInContext]: Matching field values with context
        """
    
    def get_field_datum(self, datum, field):
        """
        Get a specific field from datum.
        
        Parameters:
        - datum: DatumInContext containing dict-like value
        - field: str, field name to access
        
        Returns:
        DatumInContext or None: Field value with context, or None if not found
        """
    
    def reified_fields(self, datum):
        """
        Expand '*' wildcards to actual field names.
        
        Parameters:
        - datum: DatumInContext containing dict-like value
        
        Returns:
        tuple: Actual field names to access
        """
    
    def update(self, data, val):
        """
        Update data by setting field values.
        
        Parameters:
        - data: Input data structure
        - val: New value to set at field paths
        
        Returns:
        Updated data structure with field values set
        """

Array Index Expression

Represents array index access operations.

class Index(JSONPath):
    """
    JSONPath for array index access. Concrete syntax: [n]
    """
    
    def __init__(self, index):
        """
        Initialize index access expression.
        
        Parameters:
        - index: int, array index to access
        """
    
    def find(self, datum):
        """
        Find element at the specified index.
        
        Parameters:
        - datum: Input datum (typically list-like)
        
        Returns:
        list[DatumInContext]: Single element if index exists, empty list otherwise
        """
    
    def update(self, data, val):
        """
        Update data by setting value at the specified index.
        
        Parameters:
        - data: Input data structure (typically list-like)
        - val: New value to set at the index
        
        Returns:
        Updated data structure with value set at index
        """

Array Slice Expression

Represents array slice operations with optional start, end, and step parameters.

class Slice(JSONPath):
    """
    JSONPath for array slice access. Concrete syntax: [start:end:step] or [*]
    Includes type coercion for non-array data.
    """
    
    def __init__(self, start=None, end=None, step=None):
        """
        Initialize slice expression.
        
        Parameters:
        - start: int or None, slice start index
        - end: int or None, slice end index  
        - step: int or None, slice step size
        
        Note: If all parameters are None, acts as wildcard [*]
        """
    
    def find(self, datum):
        """
        Find elements in the specified slice.
        Coerces non-list data to single-element lists.
        
        Parameters:
        - datum: Input datum
        
        Returns:
        list[DatumInContext]: Slice elements with context
        """
    
    def update(self, data, val):
        """
        Update data by setting values in the specified slice.
        
        Parameters:
        - data: Input data structure
        - val: New value to set in slice positions
        
        Returns:
        Updated data structure with slice values set
        """

Child Composition Expression

Represents path composition operations (left.right).

class Child(JSONPath):
    """
    JSONPath that first matches the left, then the right.
    Concrete syntax: <left>.<right>
    """
    
    def __init__(self, left, right):
        """
        Initialize child composition.
        
        Parameters:
        - left: JSONPath, first expression to match
        - right: JSONPath, second expression to match from left results
        """
    
    def find(self, datum):
        """
        Find right matches from all left matches.
        
        Parameters:
        - datum: Input datum
        
        Returns:
        list[DatumInContext]: All right matches from left results
        """

Parent Access Expression

Represents parent node access (`parent` named operator).

class Parent(JSONPath):
    """
    JSONPath that matches the parent node of the current match.
    Available via named operator `parent`.
    """
    
    def find(self, datum):
        """
        Find the parent context of the datum.
        
        Parameters:
        - datum: DatumInContext with parent context
        
        Returns:
        list[DatumInContext]: Parent context
        
        Note: Will crash if no parent exists
        """

Descendant Query Expression

Represents descendant access operations (left..right).

class Descendants(JSONPath):
    """
    JSONPath that matches descendants. Concrete syntax: <left>..<right>
    Finds all nodes matching right that descend from left matches.
    """
    
    def __init__(self, left, right):
        """
        Initialize descendant query.
        
        Parameters:
        - left: JSONPath, ancestor expression
        - right: JSONPath, descendant expression to match
        """
    
    def find(self, datum):
        """
        Find all right matches that descend from left matches.
        Recursively searches through objects and arrays.
        
        Parameters:
        - datum: Input datum
        
        Returns:
        list[DatumInContext]: All descendant matches
        """
    
    def is_singular(self):
        """
        Check if this expression returns a single result.
        
        Returns:
        bool: Always False for descendant expressions
        """

Filtering Expression

Represents filtering operations (left where right).

class Where(JSONPath):
    """
    JSONPath for filtering. Concrete syntax: <left> where <right>
    Filters left matches to only those that have right matches.
    """
    
    def __init__(self, left, right):
        """
        Initialize filter expression.
        
        Parameters:
        - left: JSONPath, expression to filter
        - right: JSONPath, filter condition expression
        """
    
    def find(self, data):
        """
        Filter left matches that have right matches.
        
        Parameters:
        - data: Input data
        
        Returns:
        list[DatumInContext]: Filtered left matches
        """

Union Expression

Represents union operations (left|right).

class Union(JSONPath):
    """
    JSONPath that returns union of results. Concrete syntax: <left>|<right>
    """
    
    def __init__(self, left, right):
        """
        Initialize union expression.
        
        Parameters:
        - left: JSONPath, first expression
        - right: JSONPath, second expression
        """
    
    def find(self, data):
        """
        Return combined results from both expressions.
        
        Parameters:
        - data: Input data
        
        Returns:
        list[DatumInContext]: Combined results from left and right
        """
    
    def is_singular(self):
        """
        Check if this expression returns a single result.
        
        Returns:
        bool: Always False for union expressions
        """

Intersection Expression (Not Implemented)

Placeholder for intersection operations (left&right).

class Intersect(JSONPath):
    """
    JSONPath for intersection. Concrete syntax: <left>&<right>
    WARNING: Not implemented - find() raises NotImplementedError
    """
    
    def __init__(self, left, right):
        """
        Initialize intersection expression.
        
        Parameters:
        - left: JSONPath, first expression
        - right: JSONPath, second expression
        """
    
    def find(self, data):
        """
        Find intersection of left and right matches.
        
        Parameters:
        - data: Input data
        
        Raises:
        NotImplementedError: Intersection is not yet implemented
        """
    
    def is_singular(self):
        """
        Check if this expression returns a single result.
        
        Returns:
        bool: Always False for intersection expressions
        """

Programmatic Construction

You can build JSONPath expressions directly without parsing:

from jsonpath_rw.jsonpath import Root, Fields, Slice, Index

# Equivalent to parse('$.foo[*].bar')
expr = Root().child(Fields('foo')).child(Slice()).child(Fields('bar'))

# Equivalent to parse('users[0].name')  
expr = Fields('users').child(Index(0)).child(Fields('name'))

# Multiple fields: parse('name,email,age')
expr = Fields('name', 'email', 'age')

Install with Tessl CLI

npx tessl i tessl/pypi-jsonpath-rw

docs

cli.md

context.md

expressions.md

index.md

parsing.md

tile.json