Skip to main content

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

jetro-0.1.0.tar.gz (21.9 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

jetro-0.1.0-cp39-abi3-win_amd64.whl (2.2 MB view details)

Uploaded CPython 3.9+Windows x86-64

jetro-0.1.0-cp39-abi3-manylinux_2_28_x86_64.whl (2.5 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ x86-64

jetro-0.1.0-cp39-abi3-manylinux_2_28_aarch64.whl (2.4 MB view details)

Uploaded CPython 3.9+manylinux: glibc 2.28+ ARM64

jetro-0.1.0-cp39-abi3-macosx_11_0_arm64.whl (2.2 MB view details)

Uploaded CPython 3.9+macOS 11.0+ ARM64

File details

Details for the file jetro-0.1.0.tar.gz.

File metadata

  • Download URL: jetro-0.1.0.tar.gz
  • Upload date:
  • Size: 21.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.13.1

File hashes

Hashes for jetro-0.1.0.tar.gz
Algorithm Hash digest
SHA256 59a3a863c95805011b041cc6f97c24657d4f372e3b29be5fe608ca90d7f6cce6
MD5 de8ecd28cdd7d7999717b8961cf4101c
BLAKE2b-256 913b17361ac270d6505afad56a062731b5917d8e1a193768e9695359702fae3c

See more details on using hashes here.

File details

Details for the file jetro-0.1.0-cp39-abi3-win_amd64.whl.

File metadata

  • Download URL: jetro-0.1.0-cp39-abi3-win_amd64.whl
  • Upload date:
  • Size: 2.2 MB
  • Tags: CPython 3.9+, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: maturin/1.13.1

File hashes

Hashes for jetro-0.1.0-cp39-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 422ac95e0003998f08b488d94e2e613b88e659b7048406d460a57497d8b14d79
MD5 4e60ef8a374e448c22e0a9dc4c716566
BLAKE2b-256 242f7676cd63e0a99645b58dac56b22dfb3ebe67f386acb5ebd2b1add1192319

See more details on using hashes here.

File details

Details for the file jetro-0.1.0-cp39-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for jetro-0.1.0-cp39-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 000ac979234a9e94cb65a14d2c4d00583582c57a872b500186e1e3d6546ade0b
MD5 eaf0b60bb9531bda92107a30469c063a
BLAKE2b-256 e24d4e7582e6218d59ec6d68f161694b2beee6164051dbd133613ba107b2a38e

See more details on using hashes here.

File details

Details for the file jetro-0.1.0-cp39-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for jetro-0.1.0-cp39-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 05dcc740af104f9371886dc5fe0eef8ef93bbeabce8d978a9f53b2b696e37750
MD5 1599665411f450ab950eee8df333f312
BLAKE2b-256 85ce117e2e50e9a51cdf3bf9e93ebc092ae5081eb0c49da40f62f182d62821ce

See more details on using hashes here.

File details

Details for the file jetro-0.1.0-cp39-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for jetro-0.1.0-cp39-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 5aa48a1eeaa7dc59cd11ff338ab8e8dbd1a0de108ed179d3865f0a5c0f649798
MD5 1a0f744fb26a52ae579b8128bfbabcf6
BLAKE2b-256 78a4987f713cbb510c4d5f65d01e55aa12443406cc4d6774df327628c0a108b1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page