Query, shape, and patch JSON in one expression — at Rust speed.
Project description
jetro
Query, shape, and patch JSON in one expression — at Rust speed.
Python bindings for jetro, a JSON
query, transform, and patch DSL. Filter, project, group, aggregate,
write back to deeply nested data, and pattern-match, all in a single
expression. Streaming with demand propagation, structural bitmap index
for deep search, and a complete patch surface (.set / .modify /
.delete).
Install
pip install jetro
Wheels are published for CPython 3.9+ on linux (x86_64, aarch64), macOS (universal2), and windows (x86_64). Building from source requires a Rust toolchain.
Quickstart
from jetro import Jetro, JetroEngine
j = Jetro.from_str('{"books":[{"title":"a","price":12},{"title":"b","price":7}]}')
j.collect("$.books.len()") # 2
j.collect("$.books.filter(price > 10).map(title)") # ["a"]
j.collect("$.books.map(price).sum()") # 19
JetroEngine amortises parsing and planning across many queries:
eng = JetroEngine()
for doc in stream_of_jsons:
payload = eng.collect_bytes(doc, "$.users.filter(active).map(email)")
...
Pattern matching
j = Jetro.from_str('{"u": {"role": "admin", "id": 9}}')
j.collect("""
match $.u with {
{role: "admin", id: i} -> {tag: "a", n: i},
{role: "user", id: i} -> {tag: "u", n: i},
_ -> {tag: "x"}
}
""")
# {"tag": "a", "n": 9}
Deep search:
j.collect("""
$..match {
{tag: "click", id: i} -> i,
_ -> false
}
""")
Performance
jetro outperforms several comparable Python JSON DSL on the same
queries, and matches or beats hand-rolled Python on compound
workloads. Numbers below are median wall-clock per iteration on a
403 KB JSON document with 1000 users and ~5–50 orders each. Each
library is queried in its own idiomatic single expression for the
same semantic workload.
Warm path (cached parse + cached plan)
The document is parsed once; subsequent queries hit JetroEngine's
plan cache. Mirrors a long-running process answering many queries
against the same document.
| Workload | jetro | jmespath | jsonpath-ng | pyjq | glom (py) |
|---|---|---|---|---|---|
users.filter(active).map(email) |
86 µs | 537 µs | 2 899 µs | 18 829 µs | 32 µs |
users.filter(role=="admin").len() |
37 µs | 1 237 µs | 1 682 µs | 18 951 µs | 29 µs |
| top-5 active users by score | 43 µs | 931 µs | 2 165 µs | 20 643 µs | 84 µs |
| sum of order totals (active users) | 129 µs | 1 704 µs | 11 051 µs | 22 290 µs | 177 µs |
orders with total > 100 |
498 µs | 7 798 µs | 11 219 µs | 24 624 µs | 221 µs |
| group users by role, count | 73 µs | n/a | n/a | 20 610 µs | 68 µs |
| users with any open order ≥ 50 | 2 601 µs | 14 642 µs | 816 µs* | 28 032 µs | 379 µs |
The glom (py) column is hand-written Python list / generator
expressions over an already-parsed dict, included as a "no DSL,
maximum-speed Python" reference.
Cold path (parse + query per iteration)
Every iteration re-parses the raw bytes, then runs the query. Mirrors
the typical web-server pattern of "receive JSON request, run query,
return result" where parse cost dominates. jetro's simd-json
bytes→tape parser is several times faster than json.loads, so the
gap to several other library widens substantially.
| Workload | jetro | jmespath | jsonpath-ng | pyjq | glom (py) |
|---|---|---|---|---|---|
users.filter(active).map(email) |
574 µs | 3 828 µs | 15 984 µs | 23 526 µs | 3 340 µs |
| top-5 active users by score | 538 µs | 4 214 µs | 15 016 µs | 25 131 µs | 3 405 µs |
| group users by role, count | 547 µs | n/a | n/a | 25 037 µs | 3 339 µs |
In the cold path jetro is ~6× faster than hand-rolled Python and
7–46× faster than every other DSL because parse cost dominates
and simd-json beats json.loads by a wide margin.
Reproduce with:
pip install -r benches/requirements.txt
python benches/compare.py
Errors
from jetro import JetroParseError, JetroEvalError
JetroParseError covers JSON parse failures; JetroEvalError covers
runtime query errors. Both subclass JetroError.
API
| Class | Method | Notes |
|---|---|---|
Jetro |
from_bytes(data) -> Jetro |
accepts bytes / bytearray / memoryview |
Jetro |
from_str(text) -> Jetro |
accepts str |
Jetro |
collect(expr) -> Any |
evaluates against this document |
JetroEngine |
collect(doc, expr) -> Any |
reuses cached plan |
JetroEngine |
collect_bytes(data, expr) -> Any |
parses + queries in one call |
JetroEngine |
clear_cache() |
drops cached plans |
Language reference
See the upstream SYNTAX.md
for the full language surface.
Building from source
maturin develop --release
pytest
License
MIT.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jetro-0.1.3.tar.gz.
File metadata
- Download URL: jetro-0.1.3.tar.gz
- Upload date:
- Size: 22.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
43799f562c31a208cd2fc957e848a232e2aa848fd1aea9b2cd1de78ea5ee8da2
|
|
| MD5 |
0f3c2125bb501a10a9da55bd0091b321
|
|
| BLAKE2b-256 |
e057842cd83696ed7b9f223677383bcf49f4b11aaa75fbc6a9b1dc06783e18fd
|
File details
Details for the file jetro-0.1.3-cp39-abi3-win_amd64.whl.
File metadata
- Download URL: jetro-0.1.3-cp39-abi3-win_amd64.whl
- Upload date:
- Size: 2.3 MB
- Tags: CPython 3.9+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
07f47361f3012e36b989bac39ed8dd0361e8b1074df63d77ba0871ad9f2ce93e
|
|
| MD5 |
66c13e21b290271c128fce6c66ba2a9c
|
|
| BLAKE2b-256 |
804d5086bb4173e37b70e165a51752743562bb5d87c4b1d74a4486e059aaccaf
|
File details
Details for the file jetro-0.1.3-cp39-abi3-manylinux_2_28_x86_64.whl.
File metadata
- Download URL: jetro-0.1.3-cp39-abi3-manylinux_2_28_x86_64.whl
- Upload date:
- Size: 2.5 MB
- Tags: CPython 3.9+, manylinux: glibc 2.28+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5e40a220c022d4166b9fbf65035b9dc1620029921e3bc2b9b5d9456cbe06f0a0
|
|
| MD5 |
3fe092b908ec34c82bcd9b1c707aa474
|
|
| BLAKE2b-256 |
16cbb108eaea1ef19dec32eccb88db8f0a285b401487bff589811ae2c0f4bae2
|
File details
Details for the file jetro-0.1.3-cp39-abi3-manylinux_2_28_aarch64.whl.
File metadata
- Download URL: jetro-0.1.3-cp39-abi3-manylinux_2_28_aarch64.whl
- Upload date:
- Size: 2.4 MB
- Tags: CPython 3.9+, manylinux: glibc 2.28+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a621e49adcd671b74621fe21af77a3d850ded593de457ad78554efae84baaafa
|
|
| MD5 |
e489b3983ee9e4bcc2de0c8cefdafebd
|
|
| BLAKE2b-256 |
b83cff643fdfcd8b10e8cc169e7940ea5b3603daca10eaae9e5abeb4df9521ec
|
File details
Details for the file jetro-0.1.3-cp39-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: jetro-0.1.3-cp39-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 2.2 MB
- Tags: CPython 3.9+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: maturin/1.13.1
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b2495129e4d71a9a9e7ca7255de6e9aa26b636343d9ee3e08c1e386aeb6ddd45
|
|
| MD5 |
6a03996ef70ab41de76073bfad09c179
|
|
| BLAKE2b-256 |
d432b942b1da193a885601cb3755af14979789509cca73d9dc6897a74c0aef6a
|