Skip to main content

Python bindings for fast JSONPath resolve and value-to-path search implemented in Rust

Project description

JSONPath Sleuth

Fast Python bindings (via Rust + PyO3) for:

  • Resolving JSONPath expressions against Python dict/list JSON
  • Finding JSONPath-like paths for all occurrences of a target value
  • Extracting all JSONPath-like paths paired with their leaf values

Install / Build

  • Option A: editable dev install
    • pip install maturin
    • maturin develop -m pyproject.toml
  • Option B: build wheel
    • maturin build -m pyproject.toml
    • pip install dist/*.whl

Requires Python 3.8+.

Run Tests

  • Rust unit tests (no Python needed)

    • cargo test --no-default-features
    • Also compile PyO3 bindings: PYO3_PYTHON=$(which python3) cargo test --features python
  • Python tests (pytest)

    • Option A (quick):
      • python3 -m venv .venv && source .venv/bin/activate
      • pip install -U pip pytest maturin
      • maturin develop -m Cargo.toml --features python
      • pytest -q
    • Option B (dev extra):
      • python3 -m venv .venv && source .venv/bin/activate
      • pip install -U pip
      • pip install -e .[dev]
      • maturin develop -m Cargo.toml --features python
      • pytest -q

Notes

  • Re-run maturin develop after Rust changes to refresh the extension in your venv.
  • If pytest cannot import jsonpath_sleuth, ensure you activated the same venv used for maturin develop.

Publish

  • Build wheels + sdist

    • maturin build -m Cargo.toml --features python --release --sdist
  • TestPyPI (requires separate TestPyPI account and token)

    • Publish: maturin publish -m Cargo.toml --features python --repository-url https://test.pypi.org/legacy/ -u __token__ -p <pypi-TEST_TOKEN>
    • Install to verify: pip install -i https://test.pypi.org/simple jsonpath-sleuth
  • PyPI

    • Publish: maturin publish -m Cargo.toml --features python -u __token__ -p <pypi-PROD_TOKEN>
    • Install to verify: pip install jsonpath-sleuth

Tips

  • Bump version in both Cargo.toml and pyproject.toml before publishing a new release.
  • Tokens begin with pypi-. Avoid committing tokens; pass on the command line or configure ~/.pypirc.

Python API

Module: jsonpath_sleuth

  • resolve_jsonpath(data: dict | list, path: str) -> list[Any]
    • Returns a list of matched values for the given JSONPath. The path may omit the leading $ (it is added automatically).
  • find_jsonpaths_by_value(data: dict | list, target: Any) -> list[str]
    • Returns string paths like foo.bar[0].baz where value equals target.
  • extract_jsonpaths_and_values(data: dict | list) -> list[tuple[str, Any]]
    • Returns all JSONPath-like paths paired with their leaf values. Paths use . for object keys and [idx] for arrays.

Examples

from jsonpath_sleuth import resolve_jsonpath, find_jsonpaths_by_value, extract_jsonpaths_and_values

obj = {
    "store": {
        "book": [
            {"category": "fiction", "title": "Sword"},
            {"category": "fiction", "title": "Shield"},
        ],
        "bicycle": {"color": "red", "price": 19.95},
    }
}

# 1) Resolve JSONPath (prefix not required)
print(resolve_jsonpath(obj, "store.book[*].title"))
# -> ["Sword", "Shield"]
# Also works with explicit JSONPath:
print(resolve_jsonpath(obj, "$.store.book[*].title"))
# -> ["Sword", "Shield"]

# 2) Find paths by target value
print(find_jsonpaths_by_value(obj, "fiction"))
# -> ["store.book[0].category", "store.book[1].category"]

# 3) Extract all leaf paths and values
print(extract_jsonpaths_and_values(obj))
# -> [
#     ("store.book[0].category", "fiction"),
#     ("store.book[0].title", "Sword"),
#     ("store.book[1].category", "fiction"),
#     ("store.book[1].title", "Shield"),
#     ("store.bicycle.color", "red"),
#     ("store.bicycle.price", 19.95),
# ]

Advanced: Nested Wildcard Filters

JSONPath Sleuth supports nested wildcard filters - a powerful feature that most JSONPath libraries don't handle well:

from jsonpath_sleuth import resolve_jsonpath

data = {
    "parties": [
        {
            "name": "Alice",
            "results": [
                {"item": "A"},
                {"item": "B"}
            ]
        },
        {
            "name": "Bob",
            "results": []
        },
        {
            "name": "Charlie",
            "results": [
                {"item": "A"},
                {"item": "C"}
            ]
        }
    ]
}

# Find all parties that have ANY result with item='A'
print(resolve_jsonpath(data, "parties[?(@.results[*].item=='A')].name"))
# -> ["Alice", "Charlie"]

# This pattern works: <base>[?(@.<nested_array>[*].<field>=='<value>')].<result_field>

How it works:

  • Checks if ANY item in the nested array matches the condition
  • Returns the specified field from matching parent objects
  • Custom implementation handles what standard JSONPath libraries can't

Apostrophes in Filter Values

Filter expressions support apostrophes in comparison strings by escaping them with backslashes:

from jsonpath_sleuth import resolve_jsonpath

# Simple filter with apostrophe
data = [
    {"name": "item with's", "amount": 100},
    {"name": "plain item", "amount": 200},
    {"name": "item with's", "amount": 300},
]

result = resolve_jsonpath(data, r"[?(@.name == 'item with\'s')].amount")
# -> [100, 300]

# Nested wildcard with apostrophe
nested_data = {
    "items": [
        {"name": "item1", "results": [{"type": "value's type"}, {"type": "other"}]},
        {"name": "item2", "results": [{"type": "value's type"}]},
    ]
}

result = resolve_jsonpath(
    nested_data, 
    r"items[?(@.results[*].type=='value\'s type')].name"
)
# -> ["item1", "item2"]

# Multiple apostrophes in a single filter
multi_data = [
    {"desc": "Mary's and John's", "id": "a"},
    {"desc": "other", "id": "b"},
]

result = resolve_jsonpath(multi_data, r"[?(@.desc == 'Mary\'s and John\'s')].id")
# -> ["a"]

When writing JSONPath queries in Python:

  • Use raw strings (r"...") to avoid double-escaping: r"[?(@.name == 'user\'s name')]"
  • Escape apostrophes with backslash: \'
  • Works with both simple and nested wildcard filters

Notes

JSONPath Support

  • Standard JSONPath is powered by jsonpath-rust crate
  • Nested wildcard filters use custom implementation for enhanced functionality
  • JSONPath keys with spaces or special characters must be quoted using bracket notation
    • Example: use a['some key'].next instead of a.some key.next
    • You may omit the leading $; the resolver adds it automatically
  • Filter values with apostrophes must escape them: 'user\'s name'

Path Format

  • Paths produced by value search use . between object keys and [idx] for arrays
  • If the entire input equals the target, no paths are returned (empty list)

Supported Patterns

  • ✅ Standard wildcards: store.book[*].title
  • ✅ Filters: store.book[?(@.price < 10)].title
  • Nested wildcard filters: parties[?(@.results[*].item=='A')].name
  • ✅ Recursive descent: $..price
  • ✅ Array slices: store.book[0:2].title

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

jsonpath_sleuth-0.1.11.tar.gz (16.4 kB view details)

Uploaded Source

Built Distribution

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

jsonpath_sleuth-0.1.11-cp38-abi3-macosx_11_0_arm64.whl (881.6 kB view details)

Uploaded CPython 3.8+macOS 11.0+ ARM64

File details

Details for the file jsonpath_sleuth-0.1.11.tar.gz.

File metadata

  • Download URL: jsonpath_sleuth-0.1.11.tar.gz
  • Upload date:
  • Size: 16.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: maturin/1.13.1

File hashes

Hashes for jsonpath_sleuth-0.1.11.tar.gz
Algorithm Hash digest
SHA256 513d98266b01f312611e165fcf6e1a57cee3eabf7963e71dd2ba5102ad0bbd65
MD5 7c33fc36667957bd16ee31bc1c97aeff
BLAKE2b-256 0f650354f57bc0c1daa773237b522e41f3516d8fa63c4169aff26212d9094539

See more details on using hashes here.

File details

Details for the file jsonpath_sleuth-0.1.11-cp38-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for jsonpath_sleuth-0.1.11-cp38-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 4949e6dee9b6ab23568441d4890093c1f6d9c013472d0510eaa47f37ea8b1cb1
MD5 2e5061e0a94efe50fc0499ff240f75cc
BLAKE2b-256 09ec8357ebfae1b4b6cf0ea4d8b4c0158b464e3e98d809380fa37606b69201a4

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