NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #3494 most downloaded on PyPI
JSONPath, JSON Pointer and JSON Patch for Python.
Last release 2 months ago
07 Jul 2026
Ships fairly regularly
a new release about every 2 months
Nearly every release is documented
notes for 30 of 31 stable releases
Nothing withdrawn
no release was ever pulled
4 years old
31 releases · first in 2023
One column per quarter.
JSONPath parser recursion limit failures now raise JSONPathRecursionError , preserving the original RecursionError as the cause. JSONPathRecursionErro
Fixes
JSONPathRecursionError, preserving the original RecursionError as the cause. JSONPathRecursionError now also subclasses RecursionError, allowing existing except RecursionError handlers to continue working.Fixed lexing of quoted name selectors ending in an escaped backslash, like $['a\\']['b'] . The lexer's look-behind for the closing quote treated a quo
Fixes
$['a\\']['b']. The lexer's look-behind for the closing quote treated a quote following an escaped backslash (\\) as an escaped quote (\'), so these selectors failed to tokenize. This also broke the RFC 9535 normalized path round-trip: normalized paths produced for object keys containing backslashes could not be parsed back. See #132.Features
patch.patched(ops, data) and JSONPatch.patched(data). patched() is a non-mutating form of JSONPatch application. It always performs a deep copy of data and returns the patched copy. See #131.Added patch.atomic(patch, data) and JSONPatch.atomic(data) . atomic() is similar to apply() , but preserves input data if a patch operation fails. See
Added patch.atomic(patch, data) and JSONPatch.atomic(data). atomic() is similar to apply(), but preserves input data if a patch operation fails. See #129.
Fixed parsing of non-standard JSONPath regular expression literals containing an escaped solidus ( / ). This affected queries using the regex operator
Fixes
/). This affected queries using the regex operator =~, like $.some[?(@.thing =~ /fo\/[a-z]/)], not standard match and search functions. See #124.Fixed JSON pointers with negative indices.
Fixes
Fixed JSON pointers with negative indices.
Previously, negative indices were resolved against array-like values, but the JSON Pointer specification (RFC 6901) does not permit negative array indexes. We now raise a JSONPointerIndexError when a JSON Pointer attempts to resolve an array element using a negative index.
For users who require negative indices in JSON Pointers, you can set JSONPointer.min_int_index to a suitably negative integer, like JSONPointer.min_int_index = -(2**53) + 1.
See #116.
Fixed the JSON Patch add operation.
Previously, a JSONPatchError was raised when pointing to an array index equal to the array's length. Now we append to arrays in such cases. See #117.
These breaking changes affect the default configuration of Python JSONPath. Version 2 also introduces a new strict mode , which enforces full complian…
JSONPath syntax changes
These breaking changes affect the default configuration of Python JSONPath. Version 2 also introduces a new strict mode, which enforces full compliance with RFC 9535. See optional dependencies and the syntax guide for details.
$[foo], $['foo'], and $["foo"] were equivalent.$[foo] is a singular query selector. With an implicit root identifier, $.a[b] is equivalent to $.a[$.b]. See Singular query selector..1 is now invalid (use 0.1)1. is now invalid (use 1.0)JSONPathSyntaxError.. or .. and the following name. Whitespace before the dot is still permitted.JSONPath function extension changes
startswith(value, prefix) function extension. Returns True if both arguments are strings and prefix is a prefix of value. See the filter functions documentation.keys() function extension. It used to be a simple Python function, jsonpath.function_extensions.keys. Now it is a "well-typed" class, jsonpath.function_extensions.Keys. See the filter functions documentation.cache_capacity, debug and thread_safe arguments to jsonpath.function_extensions.Match and jsonpath.function_extensions.Search constructors.JSONPath features
regex package (if installed) instead of re. See optional dependencies.strict argument to all convenience functions, the CLI and the JSONPathEnvironment constructor. When strict=True, all non-standard extensions and relaxed parsing rules are disabled.JSONPathEnvironment.max_recursion_depth to control the maximum recursion depth of descendant segments.Python API changes
JSONPathEnvironment.fake_root_token to JSONPathEnvironment.pseudo_root_token.Low level API changes
These only affect projects customizing the JSONPath lexer or parser.
Fixed JSONPath filter context data in embedded JSONPath queries. We were failing to pass on said context data when resolving embedded queries. See #10
Fixes
Fixed the non-standard JSON Patch operation, addap . Previously it was behaving like addne . See #81 .
Fixed jsonpath.JSONPathMatch.path. It is now a "normalized path" following section 2.7 of RFC 9535.
Fixes
jsonpath.JSONPathMatch.path. It is now a "normalized path" following section 2.7 of RFC 9535.Other changes
jsonpath.match.NodeList is now re-exported as jsonpath.NodeList.jsonpath.NodeList.paths(), which returns a list of normalized paths, one for each node in the list.jsonpath.JSONPath) has changed. String literals inside filter selectors are now serialized using the canonical format, as described in section 2.7 of RFC 9535, and parentheses in filter selectors are kept to a minimum.Fixed parsing of bare name selectors that start with a reserved word. See issue #72 .
Fixes
Changes
Fixed the string representation regex literals in filter expressions. See issue #70.
Fixes
Fixed handling of JSONPath literals in filter expressions. We now raise a JSONPathSyntaxError if a filter expression literal is not part of a comparis
Fixes
JSONPathSyntaxError if a filter expression literal is not part of a comparison, membership or function expression. See jsonpath-compliance-test-suite#81.JSONPathSyntaxError in such cases.Compliance
\u escape sequences in string literals. We are adopting a policy of least surprise. The assertion is that most people will expect the JSONPath parser to behave the same as Python's JSON parser. See jsonpath-compliance-test-suite #87.true, false and null literals.Features
contains and in) to operate on object/mapping data as well as arrays/sequences. See #55.select() method to the JSONPath query iterator interface, generating a projection of each JSONPath match by selecting a subset of its values.query() method to the JSONPath class. Get a query iterator from an already compiled path.addne and addap operations to JSONPatch. addne (add if not exists) is like the standard add operation, but only adds object keys/values if the key does not exist. addap (add or append) is like the standard add operation, but assumes an index of - if the target index can not be resolved.Fixed evaluation of JSONPath singular queries when they appear in a logical expression and without a comparison operator. Previously we were evaluatin
Fixes
Fixed logical operator precedence in JSONPath filter expressions. Previously, logical _or_ (||) and logical _and_ (&&) had equal precedence. Now && bi
Fixes
||) and logical and (&&) had equal precedence. Now && binds more tightly than ||, as per RFC 9535.Features
RFC 9535 (JSONPath: Query Expressions for JSON) is now out, replacing the draft IETF JSONPath base.
RFC 9535 (JSONPath: Query Expressions for JSON) is now out, replacing the draft IETF JSONPath base.
Breaking Changes
keys function extension is no longer enabled by default. A new, well-typed keys function is planned for the future.Fixes
Features
^ and can be customized with the fake_root_token attribute on a JSONPathEnvironment subclass. Using the fake root identifier is equivalent to the standard root identifier ($), but wraps the target JSON value in an array, so the root value can be conditionally selected using a filter.Changed the exception raised when attempting to compare a non-singular filter query from JSONPathSyntaxError to JSONPathTypeError.
Breaking Changes
JSONPathSyntaxError to JSONPathTypeError.Fixes
&& or ||) and non-singular filter queries. Previously we were erroneously applying the checks for comparison expressions to logical expressions too. Now non-singular queries in logical expressions act as an existence test. See https://github.com/jg-rp/python-jsonpath/issues/45.Fixed precedence of the logical _not_ operator in JSONPath filter expressions. Previously, logical _or_ and logical _and_ had priority over _not_. See
Fixes
Fixed priority of JSONPath lexer rules. Previously, standard short tokens (like * and ?) had a higher priority than environment controlled tokens (lik
Hot fix
* and ?) had a higher priority than environment controlled tokens (like JSONPathEnvironment.keys_selector_token), making it impossible to incorporate short token characters into longer environment-controlled tokens.We now enforce JSONPath filter expression "well-typedness" by default. That is, filter expressions are checked at compile time according to the IETF J
Breaking Changes
JSONPathTypeError is raised. This can be disabled in Python JSONPath by setting the well_typed argument to JSONPathEnvironment to False, or using --no-type-checks on the command line. See #33.length() filter function is now a class and is renamed to jsonpath.function_extensions.Length.value() filter function is now a class and is renamed to jsonpath.function_extensions.Value.Fixes
$['\"'] used to be OK, it now raises a JSONPathSyntaxError. See #31.JSONPathSyntaxError for literals such as 1e2.JSONPathSyntaxError if a comparison or logical expression appeared as a filter function argument. Note that none of the built-in, standard filter functions accept arguments of LogicalType.CompoundJSONPath instances are no longer updated in-place when using .union() and .intersection(). Instead, a new CompoundJSONPath is returned. Compou
Breaking Changes
CompoundJSONPath instances are no longer updated in-place when using .union() and .intersection(). Instead, a new CompoundJSONPath is returned. CompoundJSONPath.paths is now a tuple instead of a list.Fixes
JSONPointer would resolve to the document root. The empty string is the only valid pointer that should resolve to the document root. We now raise a JSONPointerError in such cases. See #27.Features
JSONPointer.parent(), a method that returns the parent of the pointer, as a new JSONPointer (docs).JSONPointer.__truediv__() to allow creation of child pointers from an existing pointer using the slash (/) operator (docs).JSONPointer.join(), a method for creating child pointers. This is equivalent to using the slash (/) operator for each argument given to join() (docs).JSONPointer.exists(), a method that returns True if a the pointer can be resolved against some data, or False otherwise (docs).RelativeJSONPointer class for building new JSONPointer instances from Relative JSON Pointer syntax (docs, API).#<property or index>. This is to support Relative JSON Pointer's use of hash (#) when building JSONPointer instances from relative JSON Pointers.unicode_escape argument to JSONPathEnvironment. When True (the default), UTF-16 escaped sequences found in JSONPath string literals will be decoded.Fixed the string representation of a JSONPointer when built using JSONPointer.from_parts() and pointing to the document root. See #21.
Fixes
JSONPointer when built using JSONPointer.from_parts() and pointing to the document root. See #21.Changed the JSONPathMatch.parts representation of the non-standard _keys_ selector (default ~) to be ~ followed by the key name. It used to be two "pa
Breaking changes
JSONPathMatch.parts representation of the non-standard keys selector (default ~) to be ~ followed by the key name. It used to be two "parts", ~ and key index.FilterExpression subclasses must now implement children() and set_children(). These methods facilitate filter expression inspection and caching.Fixes
findall() and finditer() to accept data arguments of any io.IOBase subclass, not just TextIO.Features
JSONPointer class and methods for converting a JSONPathMatch to a JSONPointer. JSONPointer is compliant with RFC 6901 (docs).JSONPatch class. JSONPatch implements RFC 6902 (docs).jsonpath.pointer.resolve(), a convenience function for resolving a JSON Pointer (docs).jsonpath.patch.apply(), a convenience function for applying a JSON Patch (docs).jsonpath.match(), a convenience function returning a JSONPathMatch instance for the first match of a path, or None if there were no matches (docs).filter_caching argument to JSONPathEnvironment, filter expression caching is enabled by default. See [#14]env.match_class to instantiate new JSONPathMatch objects. This allows for subclassing of JSONPathMatch.jsonpath.filter.walk() for the benefit of filter expression static analysis.Fixed a bug with the filter context selector (default _) when it's used as a filter function argument.
Fixes
_) when it's used as a filter function argument.JSONPathIndexError now requires a token parameter. It used to be optional.
Breaking changes
JSONPathIndexError now requires a token parameter. It used to be optional.SelfPath and RootPath) now return a NodeList. The node list must then be explicitly unpacked by JSONPathEnvironment.compare() and any filter function that has a with_node_lists attribute set to True. This is done for the benefit of the count() filter function and standards compliance.Features
missing is now an allowed alias of undefined when using the isinstance() filter function.IETF JSONPath Draft compliance
count() filter function is now compliant with the standard, operating on a "nodelist" instead of node values.The "extra filter context" identifier now defaults to _. Previously it defaulted to #, but it has been decided that # is better suited as a current ke
Breaking changes
_. Previously it defaulted to #, but it has been decided that # is better suited as a current key/property or index identifier.Features
typeof() filter function. type() is an alias for typeof() (docs, source).isinstance() filter function. is() is an alias for isinstance() (docs, source).# will hold key associated with the current node (@). When filtering a sequence, # will hold the current index. See docs.IETF JSONPath Draft compliance
JSONPathSyntaxError.count() function's argument is array-like.Nothing published for this version
Added the built-in match filter function.
Features
match filter function.search filter function.value filter function.Fixes
@) would evaluate to undefined when a filter is applied to an array of strings.| or & now raise a JSONPathSyntaxError.IETF JSONPath Draft compliance
JSONPathSyntaxError for unescaped whitespace and control characters.JSONPathSyntaxError for empty selector segments.JSONPathIndexError if an index selector is out of range.JSONPathSyntaxError for too many colons in a slice selector.JSONPathIndexError if a slice selector argument is out of range.Behavioral change. When applied to a JSON object, filters now have an implicit preceding wildcard selector and the "current" (@) object is set to each
IETF JSONPath Draft compliance
@) object is set to each of the object's values. This is now consistent with applying filters to arrays and adheres to the IETF JSONPath Internet Draft.Added support for function extensions.
IETF JSONPath Draft compliance
length() function.count() function. count() is an alias for length().Features
keys() function.parent and children properties to JSONPathMatch. Now we can traverse the "document tree" after finding matches.parts property to JSONPathMatch. parts is a tuple of ints, slices and strs that can be used with JSONPathEnvironment.getitem() to get the matched object from the original data structure, or equivalent data structures. It is the keys, indices and slices that make up a concrete path.Fixed a bug with CompoundJSONPath.finditer() and the intersection operator (&). The intersection operation was returning just the left hand results.
Fixes
CompoundJSONPath.finditer() and the intersection operator (&). The intersection operation was returning just the left hand results.First release
First release
Your coding agent can read these notes before it upgrades. Set up the MCP server →