Operators Overview
datalogic-rs provides 59 built-in operators organized into logical categories. In the Rust crate, 33 baseline operators are always available in the default build (default = []); a further 24 canonical operators are enabled by opt-in Cargo features, and two flagd-compatible operators (fractional, sem_ver) sit behind the flagd feature. Every language binding (WASM, Node, Python, Go, JVM, .NET, PHP) ships with all operator features enabled, so the full set is available out of the box outside Rust. Counts are by canonical operator: var and ?: are accepted as input aliases of val and if, and match is an alias of switch, so the aliases are not counted separately. This section documents each operator with syntax, examples, and notes on behavior.
Operator Categories
| Category | Operators | Description |
|---|---|---|
| Variable Access | val (alias var), exists | Access and check data |
| Comparison | ==, ===, !=, !==, >, >=, <, <= | Compare values |
| Logical | !, !!, and, or | Boolean logic |
| Arithmetic | +, -, *, /, %, max, min, abs, ceil, floor | Math operations |
| Control Flow | if (alias ?:), ??, switch (alias match), type | Conditional branching |
| String | cat, substr, in, length, starts_with, ends_with, upper, lower, trim, split | String manipulation |
| Array | merge, filter, map, reduce, all, some, none, sort, slice | Array operations |
| DateTime | datetime, timestamp, parse_date, format_date, date_diff, now | Date and time |
| Missing Values | missing, missing_some | Check for missing data |
| Error Handling | try, throw | Exception handling |
| flagd-Compat | fractional, sem_ver | Feature-flag targeting (OpenFeature flagd spec); requires features = ["flagd"] |
Which operators need which Cargo feature
This split only affects the Rust crate: only the baseline set compiles in the default build (default = []), and using any other operator against an engine compiled without its feature errors at compile time as InvalidOperator. Every language binding enables all operator features, so the full set is always available there.
| Cargo feature | Operators |
|---|---|
| baseline (always on) | val/var, comparison (== … <=), and, or, !, !!, if/?:, + - * / %, min, max, cat, substr, in, map, filter, reduce, merge, all, some, none, missing, missing_some |
ext-string | length, starts_with, ends_with, upper, lower, trim, split |
ext-array | sort, slice |
ext-math | abs, ceil, floor |
ext-control | exists, ??, switch/match, type |
error-handling | try, throw |
datetime | datetime, timestamp, parse_date, format_date, date_diff, now |
flagd | fractional, sem_ver |
Operator Syntax
All operators follow the JSONLogic format:
{ "operator": [arg1, arg2, ...] }
Some operators accept a single argument without an array:
{ "var": "name" }
// Equivalent to:
{ "var": ["name"] }
Lazy Evaluation
Several operators use lazy (short-circuit) evaluation:
and: Stops at first falsy valueor: Stops at first truthy valueif: Only evaluates the matching branch?:: Only evaluates the matching branch??: Only evaluates fallback if first value is null
This is important when operations have side effects or when you want to avoid errors:
{
"and": [
{ "var": "user" },
{ "var": "user.profile.name" }
]
}
If user is null, the second condition is never evaluated, avoiding an error.
Type Coercion
Operators handle types differently:
Loose vs Strict
==and!=perform type coercion===and!==require exact type match
{ "==": [1, "1"] } // true (loose)
{ "===": [1, "1"] } // false (strict)
Numeric Coercion
Arithmetic operators attempt to convert values to numbers:
{ "+": ["5", 3] } // 8 (string "5" becomes number 5)
Truthiness
Boolean operators use configurable truthiness rules. By default (JavaScript-style):
- Falsy:
false,0,"",null,[],{} - Truthy: Everything else
Custom Operators
You can add your own operators. See Custom Operators for details.
In v5 operator registration is builder-only:
let engine = Engine::builder()
.add_operator("myop", MyOperator)
.build();
Custom operators follow the same syntax in rules:
{ "myop": [arg1, arg2] }
Note: v5 removed the
preserveoperator. Wrap literals in templating mode (Engine::builder().with_templating(true).build(), requiresfeature = "templating") if you need to emit a JSON object verbatim from a rule. Literal scalars and arrays already work inline.