Coming from json-logic-js
json-logic-js is the reference JSONLogic implementation. datalogic-rs passes the same official JSONLogic test suite, so your existing rules run unchanged. What changes is the call surface and a few defaults, listed below. See How It Compares for the wider comparison.
The one-liner
json-logic-js:
import jsonLogic from 'json-logic-js';
jsonLogic.apply({ ">": [{ var: "age" }, 18] }, { age: 21 }); // true
datalogic-rs (Node, native binding):
import { apply } from '@goplasmatic/datalogic-node';
apply({ ">": [{ var: "age" }, 18] }, { age: 21 }); // true
datalogic-rs (browser / WASM): the WASM binding takes and returns JSON text.
import init, { Engine } from '@goplasmatic/datalogic-wasm';
await init();
const engine = new Engine();
engine.evalStr('{">": [{"var": "age"}, 18]}', '{"age": 21}'); // "true"
All three return the same result. To evaluate one rule many times, compile
it once with engine.compile(rule) and call evaluate on the returned
Rule, instead of calling a one-shot in a loop.
Custom operations
json-logic-js registers operations globally:
jsonLogic.add_operation("double", (a) => a * 2);
datalogic-rs registers them per engine, and the callback works in JSON (evaluated arguments as a JSON-array string, result as a JSON string):
import { Engine } from '@goplasmatic/datalogic-node';
const engine = new Engine({}, {
double: (argsJson) => String(JSON.parse(argsJson)[0] * 2),
});
Each binding’s chapter has the exact callback shape. Name a custom
operator after a built-in and it never runs; strictOperatorNames: true
in the engine options turns that into a ConfigurationError.
Behavioral differences to know
datalogic-rs’s defaults are stricter than json-logic-js’s in a few places, and most are configurable. The ones you are most likely to notice:
- Cross-type loose equality. By default
==raises an error on a comparison that json-logic-js resolves tofalse, such as an object compared to a number. For the json-logic-js behavior, setloose_equality_errorstofalse. - Division by zero. A fractional dividend over zero returns
±f64::MAXby default (ReturnSaturated;ReturnNull,ThrowErrorandReturnInfinityare the otherdivision_by_zeromodes). An integer divided by an integer zero raisesThrown {"type": "NaN"}in every mode. - Empty objects.
{}is falsy, like[]; json-logic-js treats it as truthy. In Rust, aTruthyEvaluator::Customclosure can restore the json-logic-js rule. - Large integers. Integers keep their
i64value, so two integers above 2^53 that JavaScript rounds to one number compare as different. This applies to rules and data passed as JSON text; a JS number has already been rounded before the Node binding sees it.
These settings live on EvaluationConfig, or the config engine option in
the bindings; see Configuration.
Extensions you gain
Beyond the JSONLogic baseline, datalogic-rs adds operators the reference
engine does not ship: datetime arithmetic, string helpers (length,
starts_with, split, …), sort / slice / group_by / distinct,
keys / values / entries, try / throw, switch, and
flagd-compatible feature-flag operators (fractional, sem_ver). In the
Rust crate these sit behind Cargo features; every language binding enables
them all. See the operator overview.
You also gain checks json-logic-js does not have: engine.check(rule)
lists unknown operators (with a suggestion) and wrong argument counts
before the rule runs (Rule Analysis), and the
missing_var: "error" config setting makes a read of a missing data path
fail instead of returning null.
See Also
- Node.js Native (
@goplasmatic/datalogic-node) — drop-inapply(rule, data)and compiledRuleAPI for Node.js - Browser / Edge WASM (
@goplasmatic/datalogic-wasm) — WebAssembly package for browsers and edge workers - How It Compares — side-by-side comparison with
json-logic-jsand other engines - Operators Overview — built-in operators and extensions
- Configuration — customize equality, truthiness, and division-by-zero behavior