jq.py

Python bindings for the jq JSON query language, letting you compile and run jq filters directly from Python.

Library
PyPI
v1.12.0
452stars
BSD-2-Clause

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
60/100Good
Development Activity64
Maintenance36
Community60
Maturity60
Momentum20

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
75/100Good
Architecture78
Code Quality74
Innovation65
Learning Curve82

jq.py provides Python bindings to jq, the widely used command-line JSON processor, by compiling jq’s C library directly into a Cython extension module. Rather than shelling out to a jq binary as a subprocess, it links against jq’s core (libjq) and exposes a jq.compile(program).input_value(data) API, giving Python programs the full expressive power of jq’s filter language (.foo, map(), select(), pipes, reduce, and the rest of jq’s query syntax) without process-spawn overhead or shell-escaping concerns.

Because it bundles a specific jq release as a build dependency (via deps/jq-1.8.2.tar.gz) and compiles it from source, the package ships a self-contained binary wheel with no external jq binary required at runtime.

What You Get

  • A jq.compile(program) API returning a compiled program object that can be run repeatedly against different inputs without recompiling the filter
  • .input_value(data), .input_text(json_str), and .all()/.first()/.text() methods for feeding Python objects or raw JSON text through a jq filter and collecting results
  • Direct linkage against jq’s C library rather than subprocess invocation, avoiding shell-escaping and process-spawn overhead for high-throughput JSON transformation
  • Full access to jq’s filter language — pipes, select(), map(), reduce, string interpolation, and jq’s built-in functions — from within Python code
  • A bundled, version-pinned copy of jq’s C sources (deps/jq-1.8.2.tar.gz) so the wheel builds and runs without requiring a system-installed jq binary

Common Use Cases

  • Filtering and reshaping JSON API responses inside a Python data pipeline using familiar jq filter syntax instead of hand-written dict/list traversal code
  • Running the same jq filters used in shell scripts and CI pipelines directly from Python for consistency between tooling layers
  • High-volume JSON transformation where spawning a jq subprocess per document would be too slow
  • Validating or extracting fields from streamed JSON log lines using compiled, reusable jq programs

Under The Hood

Architecture - jq.pyx is a ~500-line Cython source file that cdef extern-declares jq’s C API (jv_kind, jv struct, jv_array_append, jq_compile, and related functions from jv.h/jq.h), then implements Python-facing classes that convert between jq’s internal jv value representation and Python objects (dicts, lists, strings, numbers, booleans, None), managing jq’s own memory-ownership conventions (consumed vs not consumed parameters noted throughout the header declarations) from the Cython layer.

Tech Stack - Built with Cython, compiling against jq’s C source (bundled in deps/jq-1.8.2.tar.gz and built via setup.py/makefile as part of the wheel build), targeting CPython. No pure-Python runtime dependencies — the compiled extension is self-contained once built.

Code Quality - tests/jq_tests.py and tests/jq_old_tests.py provide a substantial test suite exercising the compiled-program API, error handling for invalid jq programs, and JSON round-tripping, run via tox.ini across Python versions. The project has maintained compatibility with new jq releases over time (evidenced by the pinned jq-1.8.2 dependency and changelog history), though commit frequency is lower than a typical actively-growing project, consistent with a stable, narrowly-scoped binding library.

API Design - The API deliberately mirrors jq’s own two-step mental model (compile a filter, then run it against input) rather than inventing a new abstraction, so anyone familiar with the jq CLI can start using jq.compile('.foo').input_value(data).all() with almost no additional learning curve.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search