panzi-json-logic

A pure Python 3 implementation of JsonLogic and CertLogic for evaluating portable, JSON-encoded rules against data.

Library
PyPI
v1.0.1
26stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
20/100Needs Attention
Development Activity0
Maintenance0
Community12
Maturity56
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
72/100Good
Architecture80
Code Quality78
Innovation55
Learning Curve75

panzi-json-logic is a pure Python 3 implementation of the JsonLogic rule format, plus its CertLogic dialect used by the EU Digital COVID Certificate business-rules ecosystem. JsonLogic lets you express conditional logic — comparisons, boolean combinators, array operations like map/filter/reduce, string manipulation — as plain JSON objects, so the same rule can be authored once and shared between a front-end, a back-end, and a database record without re-implementing the logic in each language.

The library closely tracks the semantics of the reference json-logic-js implementation, including JavaScript’s loose-equality coercion behavior for the == operator, while also offering strict Python-native alternatives. It ships an extensible operations model: rather than mutating a shared global operator table, callers pass their own operations dictionary into jsonLogic(), making it straightforward to add custom operators or restrict which ones are available. A separate extras module adds non-standard but commonly needed operators such as now, parseTime, formatTime, timeSince, and combinations.

What You Get

  • A jsonLogic() function implementing the full JsonLogic operator set: comparisons, boolean logic, arithmetic, string operations, and array operators (map, filter, reduce, all, some, none)
  • A certLogic() function implementing CertLogic, the dialect used for EU Digital COVID Certificate business rules, including date/time operators like plusTime, before, and after
  • A pluggable operations model — pass a custom dict of operators into jsonLogic()/certLogic() instead of mutating a global registry
  • An extras module with non-standard operators (now, parseTime, formatTime, timeSince, hours, days, combinations, zip) for time-based and combinatorial rules
  • Both a strict, Python-native ===-style equality path and a JavaScript-compatible loose == path that mirrors json-logic-js coercion rules

Common Use Cases

  • Storing and evaluating conditional business rules alongside a database record instead of hard-coding them in application code
  • Sharing a single rule definition between a JavaScript front-end and a Python back-end without re-implementing the logic twice
  • Implementing CertLogic-based eligibility or validity checks, such as digital-certificate business rules
  • Building configurable feature-gating, pricing, or eligibility logic that non-developers can express as JSON rather than code
  • Filtering, mapping, or reducing structured data using rule trees that can be authored, stored, and validated independently of the codebase

Under The Hood

Architecture The library is a small, purely functional interpreter for a JSON-encoded expression tree. json_logic/apply.py defines a single recursive apply() function: it inspects the incoming logic value, and for a dict with exactly one key treats that key as the operator and its value as the argument list. Short-circuiting and context-sensitive operators — if/?:, and, or, map, filter, reduce, all, some, none — are handled as explicit branches inline in apply() because they need to control evaluation order or thread accumulator/current-item context to sub-rules, rather than eagerly evaluating all arguments up front like ordinary operators. Everything else is dispatched through a caller-supplied operations dict, resolved either by direct key lookup or, for namespaced operator names containing a dot, by walking nested dicts. json_logic/cert_logic/apply.py mirrors this same structure for the CertLogic dialect, with its own short-circuit set and builtins module. This design means the interpreter has no global mutable operator table — the operations dict is threaded explicitly through every recursive call, so composing custom operator sets or sandboxing available operations is a matter of constructing a different dict, not monkeypatching library internals.

Tech Stack Pure Python 3 (python_requires >= 3.6) with zero runtime dependencies — the entire implementation totals a few hundred lines across json_logic/apply.py, json_logic/builtins.py, and the cert_logic sub-package. It uses only the standard library: datetime/time/wsgiref.handlers.format_date_time for the extras module’s time-based operators, and json for the __main__.py CLI entry point that lets rules be evaluated from the command line. Packaging is classic setuptools via setup.cfg plus a minimal PEP 517 pyproject.toml build-system declaration; there is no build step beyond that, and the package is distributed on PyPI as panzi-json-logic.

Code Quality The project uses Python’s built-in unittest framework in a single tests.py, but the coverage is unusually thorough for its size: it loads and runs the official JsonLogic test suite (testdata/tests.json, ~298 cases) plus CertLogic’s own test suite (testdata/certlogic/*.json) and additional valid/invalid rule fixtures, dynamically generating a unittest.TestCase per fixture rather than hand-writing each assertion. Type hints are used throughout (JsonValue, Operations from json_logic/types.py), and operator functions follow a consistent op_<name>(data, *args) naming and signature convention. There is no CI configuration or linter config in the repository itself, but the reliance on upstream, community-maintained conformance test suites substitutes for a large hand-written test surface.

API Design The public surface is deliberately minimal: jsonLogic(rule, data=None, operations=BUILTINS) and certLogic(rule, data=None, operations=BUILTINS), each a single function call with sensible defaults, so getting started requires no setup beyond pip install panzi-json-logic and an import. Extending behavior is explicit and functional — spread BUILTINS into a new dict with additional entries — rather than requiring subclassing or a registration API, which keeps the mental model small. The one documented ergonomic wrinkle is substr’s UTF-16 vs. code-point semantics diverging from the JavaScript reference implementation, which the README calls out directly along with an opt-in op_substr_utf16 shim for callers who need byte-for-byte JS parity.

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