Skip to content

GoPlasmatic/datalogic-rs

Plasmatic Logo

datalogic-rs

A fast, production-ready engine for JSONLogic — Rust core, Node-native, WASM, Python, Go, React debugger.

License: Apache 2.0 Rust Crates.io Documentation npm (node) npm (wasm) PyPI


What is datalogic-rs?

datalogic-rs is a fast Rust engine for JSONLogic, a JSON-shaped language for evaluating logical rules against data. Use it as a rule engine for business logic, a JSON template engine for response shaping, or a safe expression evaluator for user-supplied formulas — and run the same rules in Rust, Node.js (native via napi), the browser (WebAssembly), Python, Go, or a React visual debugger.

JSONLogic Online Debugger Demo

Try it live in the online playground — no install required.

Pick your package

The Rust crate is the engine. Every other package wraps it for a specific runtime — same rules, same semantics, same operators. Click through to the binding's own README for install, quick start, and the full API reference for that language.

Your stack Package Install Deep-dive
Rust application or service datalogic-rs cargo add datalogic-rs crates/datalogic-rs/README.md
Node.js service (TypeScript or JS) @goplasmatic/datalogic-node npm i @goplasmatic/datalogic-node bindings/node/README.md
Browser, Deno, Bun, Cloudflare Workers, edge runtimes @goplasmatic/datalogic-wasm (WebAssembly) npm i @goplasmatic/datalogic-wasm bindings/wasm/README.md
Python service or data pipeline datalogic-py pip install datalogic-py bindings/python/README.md
Go service datalogic-go go get github.com/GoPlasmatic/datalogic-rs/bindings/go/v5 bindings/go/README.md
Java / JVM service io.github.goplasmatic:datalogic Maven Central dependency bindings/jvm/README.md
.NET service Goplasmatic.Datalogic dotnet add package Goplasmatic.Datalogic bindings/dotnet/README.md
PHP service goplasmatic/datalogic composer require goplasmatic/datalogic bindings/php/README.md
React visual rule editor / debugger @goplasmatic/datalogic-ui npm i @goplasmatic/datalogic-ui ui/README.md
C ABI for new language bindings datalogic-c (in-tree) build locally — shared FFI surface for Go/JVM/.NET/PHP bindings/c/README.md

Not sure which one? If you're writing the rules and evaluating them in the same service, pick the binding for that service's language.

On Node.js, reach for @goplasmatic/datalogic-node — it's the native build (per-platform .node prebuild via napi-rs), which is materially faster than the WASM path. The WASM package is the right pick when you need a single artifact across browser + edge runtimes (Deno, Bun, Cloudflare Workers) or when you'd rather avoid per-platform prebuilt binaries.

If you're building a UI that lets humans author rules, also pull in @goplasmatic/datalogic-ui — it consumes the WASM binding and gives you a visual editor and step-through debugger.

Documentation

The full documentation site is the long-form home for everything below: the operator reference (all 59 built-ins, organised by category), advanced topics (templating, custom operators, tracing, configuration), and an interactive playground for trying rules live without installing anything. The rest of this README is the short version.

Three things you can build with it

1. Business rules

Encode access control, feature flags, and validation as JSON. Rules are data — store them in a database, send them over an API, change them without redeploys.

let result = datalogic_rs::eval_str(
    r#"{"and": [{">=": [{"var": "age"}, 18]}, {"==": [{"var": "status"}, "active"]}]}"#,
    r#"{"age": 25, "status": "active"}"#,
).unwrap();
assert_eq!(result, "true");

2. JSON templates

Shape one JSON payload into another. With templating mode, object keys flow through to the output and operator values become computed fields — the template's structure mirrors the response you want.

// Cargo.toml: datalogic-rs = { version = "5", features = ["templating"] }
use datalogic_rs::Engine;

let engine = Engine::builder().with_templating(true).build();
let result = engine.eval_str(
    r#"{"greeting": {"cat": ["Hello ", {"var": "name"}]},
        "isAdult": {">=": [{"var": "age"}, 18]}}"#,
    r#"{"name": "Jane", "age": 25}"#,
).unwrap();
// {"greeting":"Hello Jane","isAdult":true}

3. Expression evaluation

Let users author formulas; evaluate them safely without eval(). Arithmetic, comparisons, and array reductions are all built in.

let result = datalogic_rs::eval_str(
    r#"{"+": [{"var": "subtotal"}, {"var": "tax"}, {"var": "shipping"}]}"#,
    r#"{"subtotal": 100, "tax": 8.5, "shipping": 5}"#,
).unwrap();
assert_eq!(result, "113.5");

reduce, map, filter, and sort extend the same pattern to aggregations over arrays.

One rule, every runtime

The same JSONLogic rule runs unchanged across every supported runtime. Author the rule once; evaluate it on the server, in the browser, or inside a visual editor.

Rust — server-side, native:

let result = datalogic_rs::eval_str(
    r#"{">": [{"var": "x"}, 10]}"#,
    r#"{"x": 42}"#,
).unwrap();
// "true"

Node.js (native) — services, scripts, CLIs:

import { apply } from '@goplasmatic/datalogic-node';

const result = apply({ '>': [{ var: 'x' }, 10] }, { x: 42 });
// true

Browser / Deno / Bun / Cloudflare Workers — via WebAssembly:

import init, { evaluate } from '@goplasmatic/datalogic-wasm';

await init();
const result = evaluate('{">": [{"var": "x"}, 10]}', '{"x": 42}', false);
// "true"

Python — services, scripts, data pipelines:

from datalogic_py import apply

result = apply({">": [{"var": "x"}, 10]}, {"x": 42})
# True

Go — services, CLIs:

import datalogic "github.com/GoPlasmatic/datalogic-rs/bindings/go/v5"

out, _ := datalogic.Apply(`{">": [{"var": "x"}, 10]}`, `{"x": 42}`)
// "true"

React — drop-in visual debugger / editor:

import { DataLogicEditor } from '@goplasmatic/datalogic-ui';

<DataLogicEditor
  value={{ ">": [{ "var": "x" }, 10] }}
  data={{ x: 42 }}
/>

See the rule run live in your browser at the online playground.

Choosing your API: five tiers, one engine

Every binding exposes the same conceptual ladder — pick the entry point that matches how often you evaluate and how much control you want over allocation.

What it is Use when
Tier 0 — Module-level one-shoteval_str, eval, eval_into, compile Quick scripts, ad-hoc evaluation, no custom configuration
Tier 1 — Engine one-shotEngine::eval* You need custom operators, non-default config, or templating mode
Tier 2 — Session (hot loop)Engine::session() + Session::eval* You're evaluating compiled rules many times — services, batch jobs, request handlers
Tier 3 — Zero-copy evaluateEngine::evaluate(&Logic, data, &Bump) You want results that borrow directly into a caller-owned arena (specialised use)
Tier 4 — Traced evaluationEngine::trace() Debugging, visualising execution, building inspector UIs

Most callers want Tier 0 or Tier 2. Tier 0 is the right default for trying something out; reach for Tier 2 once the same rule is being evaluated repeatedly. Bindings expose the same ladder under language-idiomatic names — see each binding's README for the exact call sites. For the Rust deep-dive, including code per tier and runnable examples, see crates/datalogic-rs/README.md.

Highlights

  • Cross-platform — same engine, same rules in Rust, Node.js (native), browsers + edge runtimes (WASM), Python, Go, and a React UI
  • 59 built-in operators with full JSONLogic spec compliance — 57 in the default build plus 2 opt-in OpenFeature flagd-compatible operators (fractional, sem_ver) behind features = ["flagd"]
  • Compile once, evaluate millions of timesLogic is Send + Sync; share via Arc
  • Zero unsafe — built with #![forbid(unsafe_code)]
  • Arena-allocated evaluationbumpalo-backed; read-through ops borrow zero-copy from the input
  • serde_json is optional — opt in only when you need the value boundary
  • Configurable — NaN handling, division-by-zero, truthiness modes, numeric coercion
  • Custom operators via a simple trait — same idea exposed in every binding
  • Visual debugger + execution tracing for diagnosing rules

Performance

datalogic-rs is built for repeated evaluation. Compiled rules dispatch through a single OpCode enum (no string lookups), values live in a bumpalo::Bump arena (no per-result heap allocation), and read-through operators like var borrow zero-copy from the caller's input.

Geomeans across 44 suites (Apple M2 Pro, macOS 26.3, Rust 1.93, Node 24; median of 3 samples per cell, ~200 ms wall budget — see tools/benchmark/BENCHMARK.md for the per-suite matrix, methodology, and caveats):

Library Config / setup Geomean ns/op vs dlrs:engine
datalogic-rs (native Rust, this repo) precompiled — dlrs:engine 9.7
json-logic-engine (TotalTechGeek, JS) compiled — json-logic-engine:compiled 47.2 4.9×
json-logic-engine (TotalTechGeek, JS) interpreted — json-logic-engine 160.3 16.5×
jsonlogic-rs (bestowinc, native Rust) default — jsonlogic-rs 218.0 22.5×
json-logic-js (jwadhams reference, JS) default — json-logic-js 423.5 43.7×
@goplasmatic/datalogic-wasm (WebAssembly, run in Node) compiled — dlrs:wasm:compiled 855.6 88.2×

The WASM row above measures the WebAssembly build running in Node — the artifact you'd ship to browsers / Deno / Bun / Cloudflare Workers, not the Node-native package. Node consumers should reach for @goplasmatic/datalogic-node (per-platform napi-rs prebuilds) for production workloads; it shares the same Rust core as the dlrs:engine row above with only the napi boundary added, so its ceiling sits much closer to native Rust than to WASM. Native-Node benchmark numbers will land here once the suite is wired up against the @goplasmatic/datalogic-node prebuild.

Numbers are macOS / Apple Silicon — Linux x86_64 will distribute differently. Quote ratios, not absolute ns/op, when citing.

Migrating from v4

v5 is a breaking release with a hard cliff: no compat feature, no deprecated method shims inside the v5 crate. Headline changes: DataLogicEngine, CompiledLogicLogic, OperatorCustomOperator; one-shot evaluation is now eval_str (returns String) or eval_into::<T> (returns a typed value); custom operators receive pre-evaluated &DataValue<'a> args and an EvalContext; operator registration is builder-only; serde_json lives behind the serde_json feature. See MIGRATION.md for the full v4 → v5 cookbook.

Resources

Contributing

See CONTRIBUTING.md for the contribution workflow, DEVELOPMENT.md for local setup and per-package commands, and ARCHITECTURE.md for the cross-package design.

About Plasmatic

Created by Plasmatic, building open-source tools for financial infrastructure and data processing.

License

Licensed under Apache 2.0. See LICENSE for details.

About

A fast, type-safe Rust implementation of JSONLogic for evaluating logical rules as JSON. Perfect for business rules engines and dynamic filtering in Rust applications.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors