mrkeyoor.com_
Sat 08 Aug 20:58 UTC
PyPIUtilsupdated 08 Aug 2026

jsonpath-python

jsonpath-python is a zero-runtime-dependency JSONPath evaluator and updater implemented with a direct Python parser. It supports child selection, recursive descent, wildcards, slices, filters, regex tests, membership tests, custom sort expressions, field extraction, value updates, and path output. Its syntax extends the original Goessner-style JSONPath rather than implementing RFC 9535. That makes it unusually capable for manipulating Python dictionaries and lists, but expressions are tied to this package's dialect.

Verdict

Excellent value when you own the expressions and want zero dependencies plus sorting and updates. Skip it when JSONPath portability or RFC 9535 behavior is part of the contract.

API stability3/5The public surface is compact, centered on JSONPath, search, compile, parse, and update, and version 1.1.6 documents explicit exceptions. Stability risk comes from the dialect rather than the number of methods: sorter, extractor, special-field quoting, and filter behavior are package-specific extensions, and the project is still in a 1.x line with recent syntax fixes. Pin the package and test a representative expression corpus.
Docs4/5The README is the documentation and is unusually complete for a small package. It lists every operator and shows child selection, recursive descent, slicing, filters, regex, membership, multidimensional sorting, extraction, updates, cached search, compile, path output, and exception types against concrete data. It also admits nonconformance with RFC 9535. What is missing is a separate compatibility matrix and deeper complexity or security guidance.
Maintenance4/5Version 1.1.6 was uploaded in May 2026, the repository was pushed the same day, PyPI marks it Production/Stable, and GitHub reported no open issues or pull requests at collection time. Recent changelog entries cover real parser corrections rather than metadata-only releases. The caution is bus factor and scale: roughly 49 stars and a small codebase suggest maintenance depends heavily on one project owner.
Ecosystem2/5The package has high installation volume and no runtime dependency burden, but its strongest features are its own extensions rather than interoperability. RFC 9535 tools cannot be assumed to accept its sorter, extractor, update semantics, or single-quote field notation, and there is little visible adapter or plugin ecosystem around the repository. Its ecosystem is therefore Python-local and expression-dialect-specific despite the familiar JSONPath name.

Use it if

  • You want JSONPath selection and in-place updates without runtime dependencies
  • You need package-specific sorting, field extraction, regex, or membership expressions in addition to ordinary selection
  • You repeatedly evaluate the same expression and want a compile function plus cached search helper
  • You control both expression producers and consumers, so portability to an RFC 9535 engine is not required
Skip it if

Setup reality

pip install jsonpath-python is genuinely small: version 1.1.6 supports Python 3.8 and newer and declares no runtime dependencies. The import is from jsonpath, not jsonpath_python, which is an easy first mistake. The simple search(expression, data) function uses an internal LRU cache, while compile(expression) returns a reusable JSONPath object; pick one clear application convention rather than recompiling inside tight loops. The bigger setup decision is syntax ownership. The README states that this implementation modifies and extends the original JSONPath syntax and is not the choice for strict RFC 9535 compatibility. Its sorter /(...), extractor (...), special-field quoting, and update method will not move cleanly to many other engines. Compared string literals inside filters must use double quotes because single quotes identify fields containing dots or spaces. Output defaults to values, but path mode changes the result contract and must be chosen consistently if downstream code stores or edits paths. Invalid syntax can raise ExprSyntaxError, while incompatible types can raise JSONPathTypeError; neither should be flattened into an empty match because an empty list is also a valid query result. update changes the original object and accepts a callable, so copy data first when callers expect persistence-style immutability. Finally, do not accept an unrestricted expression language at an external API boundary without limits. Recursive descent, regexes, wide filters, and sorts can consume meaningful CPU and memory on large documents even when the parser itself has no dependencies.

Patterns

Select values from every array itemselect-child-values

from jsonpath import JSONPath

data = {"books": [{"title": "A"}, {"title": "B"}]}
titles = JSONPath("$.books[*].title").parse(data)

parse returns a list of matches even when only one value matches.

Find a field at any depthsearch-recursively

from jsonpath import search

prices = search("$..price", document)

search uses LRU caching for repeated expressions, but recursive descent can still scan a large document.

Filter objects with multiple conditionsfilter-items

from jsonpath import JSONPath

cheap_fiction = JSONPath(
    '$.books[?(@.category=="fiction" and @.price<10)].title'
).parse(data)

Compared strings must use double quotes; this dialect reserves single quotes for another field-selection form.

Select items containing a tagfilter-membership

matches = JSONPath(
    "$.items[?('featured' in @.tags)]"
).parse(data)

This in operator is a package extension and should not be assumed portable to other JSONPath engines.

Match a field with a regular expressionfilter-regex

matching = JSONPath(
    "$.books[?(@.title =~ /.*Python.*/)].title"
).parse(data)

Regex evaluation over attacker-controlled expressions or very large inputs needs application-level limits.

Take a Python-style array sliceslice-array

middle = JSONPath("$.books[1:3]").parse(data)
every_other = JSONPath("$.books[::2]").parse(data)

The slice follows this package's Python-like behavior; test negative bounds if expressions must move between engines.

Sort objects before selecting valuessort-results

ascending = JSONPath("$.books[/(price)].title").parse(data)
descending = JSONPath("$.books[/(~price)].title").parse(data)

The /(...) sorter and ~ descending marker are jsonpath-python extensions, not RFC 9535 syntax.

Project selected fields into dictionariesextract-fields

summary = JSONPath(
    "$.books[/(price)].(title,price)"
).parse(data)

Field extraction with (...) is package-specific; consumers should not treat the expression as portable JSONPath.

Update every matching valueupdate-matches

from jsonpath import JSONPath

JSONPath("$.books[*].price").update(
    data, lambda price: round(price * 0.9, 2)
)

update mutates data in place; use copy.deepcopy first when other code shares the original object.

Distinguish bad syntax from no matcheshandle-expression-errors

from jsonpath import JSONPath, ExprSyntaxError, JSONPathTypeError

try:
    values = JSONPath(expression).parse(data)
except (ExprSyntaxError, JSONPathTypeError) as exc:
    raise ValueError(f"invalid JSONPath: {exc}") from exc

An empty result is valid and differs from an invalid expression or an incompatible comparison type.

Alternatives

PackageRegistryPick it when
jsonpath-ngPyPIYou want a mature parser with an AST-oriented extended syntax and a larger installed ecosystem
jsonpath2PyPIYou prefer a different JSONPath implementation and can validate its dialect against your expression corpus
jmespathPyPIYou can choose a standardized query language designed for projections and transformations rather than JSONPath compatibility