mrkeyoor.com_
Sun 20 Sept 02:39 UTC
PyPIUtilsupdated 19 Sept 2026

jmespath review

jmespath 1.1.0 evaluates a standardized query language against JSON-shaped Python values. `search()` can select nested fields, filter and slice arrays, flatten projections, call built-in functions, and construct new lists or mappings without changing the input. `compile()` parses an expression once for repeated use. The 1.1.0 release fixes a parser-cache concurrency bug, supports Python 3.12 through 3.14, drops Python 3.7 and 3.8, and now requires Python 3.9 or newer.

Verdict

jmespath 1.1.0 installed in 0.2 seconds as 1 dependency-free package using 1 MB, with 0 audit findings in our sandbox; it fits portable read-only queries over JSON-shaped data. Keep fixed application logic in Python, and choose JSONPath when recursive descent is a hard requirement.

We installed it

Lab card: what happened when we installed jmespathScreenshot of jmespath documentation
Install✓ · 0.2s1 package on disk · 1 MB
Importimport jmespath in 0.12s · pure Python · requires Python >=3.9
Known vulns0(pip-audit)

Answers from our run

Does jmespath install cleanly?

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

What does jmespath need to run?

Python >=3.9, and nothing compiled: it is pure Python. In our run import jmespath succeeded in 0.12s.

jmespath or jsonpath-ng: which should you use?

jsonpath-ng: Choose it for JSONPath syntax, recursive descent, and matches that retain paths into the document. jmespath 1.1.0 installed in 0.2 seconds as 1 dependency-free package using 1 MB, with 0 audit findings in our sandbox; it fits portable read-only queries over JSON-shaped data.

When should you not use jmespath?

The query needs JSONPath recursive descent to locate a field at any depth; JMESPath has no equivalent .. operator.

API stability5/5The public Python surface centers on search(), compile(), and Options, while expression behavior follows a published grammar and cross-implementation compliance suite. Version 1.1.0 changes supported Python versions and repairs cache concurrency without changing normal query syntax. The explicit weak point is custom_functions, which the README still marks experimental and therefore outside the same compatibility promise.
Docs4/5jmespath.org provides a tutorial, worked examples, the full specification, grammar, built-in function signatures, and proposals. The Python README covers search, precompilation, Options, ordered mappings, and custom functions with executable examples. Projection behavior, null propagation, quoting rules, and function type errors are spread across language documentation, so a quick example alone is insufficient for production expressions.
Maintenance3/5PyPI lists 1.1.0 as current, GitHub recorded a push on April 20, 2026, and the unarchived repository had 72 open issues and pull requests plus 2,451 stars. The latest release fixed concurrent parser-cache access and added Python 3.12 through 3.14 support. The standardized language moves deliberately, but the issue queue and long intervals mean implementation fixes may not arrive quickly.
Ecosystem4/5PyPI Stats reported 148,103,889 downloads in the latest week. JMESPath has implementations in several languages, a shared compliance corpus, direct AWS CLI support through `--query`, and Boto3 PageIterator integration. That makes expressions portable across useful boundaries, although its intentionally small built-in language has less extension space than jq or Python-native transformation packages.

Discussed on

  1. hnJMESPath – A query language for JSON219 points
  2. hnShow HN: jid – JSON Incremental Digger v1.1.0 with JMESPath support9 points
  3. hnJMESPath – a query language for JSON6 points
  4. hnAdvanced AWS CLI JMESPath Query Tricks4 points
  5. hnJMESPath is a query language for JSON4 points

Use it if

  • Users or configuration files need a constrained, read-only query language over dictionaries and lists.
  • One expression should work in Python, the AWS CLI `--query` flag, and Boto3 paginator searches.
  • The program repeatedly applies a precompiled field-selection or filtering expression to many documents.
  • Cross-language behavior matters enough to prefer an ABNF grammar and shared compliance tests over a homegrown selector.
Skip it if

Setup reality

We installed jmespath 1.1.0 in a fresh Python 3.12 Bookworm container in 0.2 seconds. It added 1 package, occupied 1 MB, and pip-audit reported 0 known vulnerabilities. The pure-Python distribution has 0 direct dependencies, requires Python 3.9 or newer, and uses the MIT license. import jmespath completed in 0.12 seconds. The wheel does not include py.typed, so typed projects should expect incomplete package-level checking.

There is no account, credential, daemon, or configuration file. Most setup time goes into learning expression literals and projections. Strings use JMESPath quoting, while JSON numbers, booleans, arrays, and objects commonly sit inside backticks. [*] preserves projection nesting in places where [] flattens a level, so realistic fixtures should cover empty arrays and missing members.

A missing path usually returns Python None rather than raising. That behavior is convenient for optional fields and dangerous for misspellings, so validate results that are required. Built-in functions also enforce JMESPath types at runtime. User-provided expressions cannot call arbitrary Python, but a long expression over a large in-memory document still consumes application CPU.

Call compile() once when one query runs against many records; version 1.1.0 specifically fixes concurrent access to the parser cache. Options can replace the result mapping class or install custom functions. Custom functions require _func_ method names and signature decorators, and the project still calls their API experimental. Boto3 paginator search evaluates the expression once per response page, which can yield individual list elements instead of one combined result.

Patterns

Read a nested value select-nested-field

import jmespath

data = {'user': {'profile': {'name': 'Ana'}}}
name = jmespath.search('user.profile.name', data)
missing = jmespath.search('user.profile.email', data)

A missing path returns None, so check `missing` explicitly when the field is required.

Reuse one parsed query compile-expression

expression = jmespath.compile('items[*].id')
for page in pages:
    ids = expression.search(page)

compile() avoids reparsing the same expression for every document; 1.1.0 also fixes concurrency around the parser cache.

Filter by string and number filter-array

data = {'jobs': [
    {'id': 'a', 'state': 'ready', 'retries': 1},
    {'id': 'b', 'state': 'failed', 'retries': 4},
]}
ready = jmespath.search("jobs[?state=='ready'].id", data)
retried = jmespath.search('jobs[?retries > `2`].id', data)

The numeric value is a JSON literal inside backticks; string comparison uses quoted JMESPath text.

Create a new object shape reshape-result

result = jmespath.search(
    'jobs[*].{job_id: id, status: state}',
    data
)

A multiselect hash builds new mappings and leaves the input dictionaries unchanged.

Flatten one array level flatten-projection

data = {'groups': [
    {'users': [{'id': 1}, {'id': 2}]},
    {'users': [{'id': 3}]}
]}
nested = jmespath.search('groups[*].users[*].id', data)
flat = jmespath.search('groups[].users[].id', data)

The first expression preserves nested lists; empty brackets flatten a projection level and return one list of IDs.

Select the largest item sort-and-pick

data = {'packages': [
    {'name': 'a', 'downloads': 10},
    {'name': 'b', 'downloads': 40}
]}
name = jmespath.search(
    'sort_by(packages, &downloads)[-1].name', data
)

sort_by requires the expression to produce comparable values; null or mixed types can raise a runtime type error.

Filter Boto3 paginator output query-boto3-pages

paginator = ec2.get_paginator('describe_instances')
ids = paginator.paginate().search(
    "Reservations[].Instances[?State.Name=='running'].InstanceId[]"
)
for instance_id in ids:
    print(instance_id)

PageIterator.search runs once per API page and yields each element when that page's expression result is a list.

Register a Python function add-custom-function

from jmespath import functions

class Extra(functions.Functions):
    @functions.signature({'types': ['string']})
    def _func_slug(self, value):
        return value.lower().replace(' ', '-')

options = jmespath.Options(custom_functions=Extra())
value = jmespath.search('slug(title)', data, options=options)

Custom function support is experimental. Method names must start with `_func_`, and signatures use JMESPath type names.

Alternatives

PackageRegistryPick it when
jsonpath-ngPyPIChoose it for JSONPath syntax, recursive descent, and matches that retain paths into the document.
glomPyPIChoose it for Python-native nested access, defaults, validation, assignment, and larger transformations.
jqPyPIChoose the binding when the team already uses jq's broader transformation and streaming language.

More utils guides

lru-cache · type-fest · ajv · 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.