mrkeyoor.com_
Wed 23 Sept 00:32 UTC
PyPIUtilsupdated 21 Sept 2026

jsonpath-python review

jsonpath-python 1.1.6 selects, sorts, projects, and updates values inside Python dictionaries and lists using an extended JSONPath expression. It understands child access, recursive descent, wildcards, Python-style slices, Boolean filters, membership tests, regex matching, multi-field sorting, and path output. The import name is jsonpath, and repeated expressions can use compile() or the module's cached search() helper. This is the project's own Goessner-derived dialect, not an RFC 9535 implementation. Version 1.1.6 closes regex filter injection after 1.1.5 replaced unsafe eval-based filter handling. Our Python 3.12 sandbox imported the pure-Python package in 0.24 seconds, but the distribution does not include py.typed.

Verdict

jsonpath-python 1.1.6 installed in 0.2 seconds, used 1 MB, imported in 0.24 seconds, and returned 0 pip-audit findings in our sandbox, but it also brought 5 direct dependencies and no py.typed marker. Use it when you own the query dialect and need sorting or mutation; use an RFC 9535 implementation when expressions are a shared contract.

We installed it

Lab card: what happened when we installed jsonpath-pythonScreenshot of jsonpath-python documentation
Install✓ · 0.2s1 package on disk · 1 MB
Importimport jsonpath in 0.24s · pure Python · requires Python >=3.8
Known vulns0(pip-audit)

Answers from our run

Does jsonpath-python install cleanly?

Yes. In a fresh container with an empty cache, pip install jsonpath-python finished in 0.2s, leaving 1 package and 1 MB on disk. pip-audit reported no known vulnerabilities.

What does jsonpath-python need to run?

Python >=3.8, and nothing compiled: it is pure Python. In our run import jsonpath succeeded in 0.24s.

jsonpath-python or jsonpath-ng: which should you use?

jsonpath-ng: Use it when an AST-oriented JSONPath implementation, named operators, and a larger Python user base fit better than this package's compact dialect. jsonpath-python 1.1.6 installed in 0.2 seconds, used 1 MB, imported in 0.24 seconds, and returned 0 pip-audit findings in our sandbox, but it also brought 5 direct dependencies and no py.typed marker.

When should you not use jsonpath-python?

Expressions cross service or vendor boundaries. The README says the syntax is modified and extended, and recommends another implementation for strict RFC 9535 behavior.

API stability3/5The working API is small: JSONPath(expr).parse(), update(), search(), and compile(), with VALUE and PATH result modes. Version 1.1 added the cached helpers and mutation method while correcting path output, quoted keys, bracket filters, field extraction, and mixed-type sorting. Those were useful fixes, but they changed behavior in central expression paths. The package-specific sorter, extractor, quoting rules, and filter grammar also mean stability must be tested against your exact query corpus rather than inferred from the JSONPath name.
Docs4/5The README gives examples for child selection, multiple fields, wildcards, recursive descent, slices, compound filters, membership, regex, ascending and descending sort, nested sort keys, field projection, mutation, cached search, compilation, and the two exception classes. It plainly says the dialect is modified and is not the strict RFC 9535 choice. Missing pieces include a formal grammar, thread-safety guidance for cached objects, a compatibility table against the RFC, and detailed limits for hostile expressions or large documents.
Maintenance4/5PyPI published 1.1.6 on May 7, 2026, and GitHub shows a push at the same time with 0 open issues or pull requests. The unarchived repository released concrete security repairs in 1.1.5 and 1.1.6, covering eval-based remote code execution and regex filter injection. Earlier 1.1 releases repaired quoted keys, bracket filters, field extraction, path output, and mixed-type sorting. The caution is project scale: GitHub has 50 stars, so review and continuity appear concentrated in a small maintainer base.
Ecosystem2/5The current package record carries 5,221,445 weekly downloads, but interoperability is limited by its expression dialect. RFC 9535 engines cannot be assumed to understand /(...) sorting, (...) extraction, the single-quote field convention, Python-like filters, or update(). PyPI metadata targets Python 3.8 through 3.13 and labels the project Production/Stable. The pure-Python build broadens platform reach, while the missing py.typed marker and lack of a visible adapter ecosystem keep integration mostly at the direct function-call level.

Use it if

  • Your program owns both the expressions and the Python data, and it needs selection plus in-place updates from one small API.
  • Queries need this package's sorter /(...), field extractor (...), regex =~, or membership operators beyond basic JSONPath navigation.
  • The same expressions run repeatedly, so the 128-entry module cache or a compiled JSONPath object can avoid reparsing them.
  • Callers need either matched values or concrete JSONPath strings that identify the matching locations.
Skip it if

Setup reality

Our fresh Python 3.12 sandbox installed jsonpath-python 1.1.6 in 0.2 seconds. The environment contained 1 package using 1 MB, and import jsonpath completed in 0.24 seconds. pip-audit found 0 known vulnerabilities. The measured package has 5 direct dependencies, requires Python 3.8 or newer, is pure Python, and uses the MIT license. It does not ship py.typed, so typed projects may need a stub or missing-import rule.

No credential or config file is required. Install name and import name differ: pip installs jsonpath-python, while code imports JSONPath, search, or compile from jsonpath. The larger commitment is expression syntax. Filters borrow Python comparison, logical, membership, and regex forms. Compared string values use double quotes because single quotes mark field names containing dots or spaces in this dialect.

search() and compile() share a module-level LRU cache capped at 128 expressions. A compiled JSONPath object can parse many documents, but parse() stores the requested VALUE or PATH result mode on that object. Avoid sharing one cached instance across concurrent calls that mix result modes; construct separate JSONPath objects or serialize those calls. Invalid expressions raise ExprSyntaxError, and incompatible operations such as mixed-type sorting can raise JSONPathTypeError.

update() finds matching paths and mutates the supplied dictionary or list, using either a fixed value or a callback result. Copy the document first when callers expect an immutable transform. Version 1.1.5 removed arbitrary code execution through eval in filters, and 1.1.6 blocked regex filter injection. Those fixes make 1.1.6 the minimum sensible pin, while CPU and memory limits remain your responsibility for recursive descent, regex, and sorting on untrusted input.

Patterns

Read one nested field select-field

from jsonpath import JSONPath

data = {"store": {"book": [{"title": "Dune"}]}}
titles = JSONPath("$.store.book[*].title").parse(data)
assert titles == ["Dune"]

parse() returns a list even when the expression has one match. A missing match returns an empty list.

Find a field at any depth recursive-descent

from jsonpath import search

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

Recursive descent walks every reachable branch under the root. Put a size limit around externally supplied documents.

Select every second item slice-array

from jsonpath import JSONPath

odd_positions = JSONPath("$.items[1::2]").parse(data)

Array slices follow Python start:end:step rules, including omitted and negative bounds.

Combine numeric filter conditions filter-numbers

from jsonpath import JSONPath

midrange = JSONPath("$.items[?(@.price >= 10 and @.price < 20)]").parse(data)

Filters accept Python-style comparison and logical operators. Mixed or missing value types need tests against your real documents.

Match a value inside a list filter-membership

from jsonpath import JSONPath

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

Single quotes delimit the literal on the left of this membership expression. Compared strings after == or != use double quotes in this dialect.

Filter a string with a regular expression filter-regex

from jsonpath import JSONPath

books = JSONPath(r"$.books[?(@.title =~ /^The /)]").parse(data)

Version 1.1.6 fixed regex filter injection. Regex evaluation can still be expensive, so expressions from users need length and complexity limits.

Read a key containing punctuation access-special-key

from jsonpath import JSONPath

data = {"build.version": "1.4.0"}
value = JSONPath("$.'build.version'").parse(data)
assert value == ["1.4.0"]

Single-quoted field notation is marked experimental in the README and is specific to this implementation.

Sort by two fields sort-results

from jsonpath import JSONPath

ordered = JSONPath("$.books[/(category,price)]").parse(data)
descending = JSONPath("$.books[/(~price)]").parse(data)

/(...) is this package's sorter extension. A tilde reverses a field, and incompatible field types can raise JSONPathTypeError.

Project selected fields extract-fields

from jsonpath import JSONPath

rows = JSONPath("$.books[*].(title,price)").parse(data)

The extractor returns dictionaries containing the named fields. Missing keys are omitted after the 1.1 field-extraction fix.

Return locations instead of values return-paths

from jsonpath import JSONPath

query = JSONPath("$.books[*].price")
paths = query.parse(data, result_type="PATH")

PATH mode changes each result into a JSONPath location. parse() stores the mode on the JSONPath object, so do not mix modes concurrently on one instance.

Change every matched value update-values

from jsonpath import JSONPath

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

update() mutates data in place and returns the same root object. Copy the structure first if other callers retain it.

Compile a query for repeated use reuse-expression

from jsonpath import compile

find_ids = compile("$.records[*].id")
first = find_ids.parse(batch_one)
second = find_ids.parse(batch_two)

compile() uses the module's 128-entry LRU cache. Construct JSONPath directly when a shared cached instance is undesirable.

Alternatives

PackageRegistryPick it when
jsonpath-ngPyPIUse it when an AST-oriented JSONPath implementation, named operators, and a larger Python user base fit better than this package's compact dialect.
jsonpath2PyPIUse it when its parser and expression behavior match an existing query corpus; verify the exact operators before migrating.
jmespathPyPIUse it when you can choose a specified projection language instead of preserving JSONPath syntax or in-place update behavior.

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.