Crates.io | datalogic-rs |
lib.rs | datalogic-rs |
version | 4.0.3 |
created_at | 2024-11-19 02:20:35.614503+00 |
updated_at | 2025-09-18 15:15:03.630307+00 |
description | 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. |
homepage | https://github.com/GoPlasmatic/datalogic-rs |
repository | https://github.com/GoPlasmatic/datalogic-rs |
max_upload_size | |
id | 1452835 |
size | 579,402 |
A fast, production-ready Rust engine for JSONLogic.
Effortlessly evaluate complex rules and dynamic expressions with a powerful, memory-efficient, and developer-friendly toolkit.
datalogic-rs
brings the power of JSONLogic to Rust, focusing on speed, safety, and ease of use. Whether youâre building feature flags, dynamic pricing, or complex validation, this engine is designed to be flexible and robust.
Whatâs New in v4? Weâve redesigned the API to be more ergonomic and developer-friendly. If you need maximum speed with arena allocation, v3 is still available and maintained. Choose v4 for a smoother experience, or stick with v3 for raw performanceâboth are supported.
serde_json::Value
.use datalogic_rs::DataLogic;
use serde_json::json;
let engine = DataLogic::new();
let logic = json!({ ">": [{ "var": "age" }, 18] });
let compiled = engine.compile(&logic).unwrap();
let result = engine.evaluate_owned(&compiled, json!({ "age": 21 })).unwrap();
assert_eq!(result, json!(true));
use datalogic_rs::DataLogic;
use serde_json::json;
let engine = DataLogic::new();
let result = engine.evaluate_json(
r#"{ "+": [1, 2] }"#,
r#"{}"#
).unwrap();
assert_eq!(result, json!(3));
use datalogic_rs::DataLogic;
use serde_json::json;
use std::sync::Arc;
let engine = Arc::new(DataLogic::new());
let logic = json!({ "*": [{ "var": "x" }, 2] });
let compiled = engine.compile(&logic).unwrap();
// Share across threads
let engine2 = Arc::clone(&engine);
let compiled2 = Arc::clone(&compiled);
std::thread::spawn(move || {
engine2.evaluate_owned(&compiled2, json!({ "x": 5 })).unwrap();
});
Add this to your Cargo.toml
:
[dependencies]
datalogic-rs = "4.0"
# Or use v3 if you need arena-based allocation for maximum performance
# datalogic-rs = "3.0"
use datalogic_rs::DataLogic;
use serde_json::json;
let engine = DataLogic::new();
let logic = json!({
"if": [
{ ">=": [{ "var": "age" }, 18] },
"adult",
"minor"
]
});
let compiled = engine.compile(&logic).unwrap();
let result = engine.evaluate_owned(&compiled, json!({ "age": 25 })).unwrap();
assert_eq!(result, json!("adult"));
use datalogic_rs::DataLogic;
use serde_json::json;
let engine = DataLogic::new();
let logic = json!({
"filter": [
[1, 2, 3, 4, 5],
{ ">": [{ "var": "" }, 2] }
]
});
let compiled = engine.compile(&logic).unwrap();
let result = engine.evaluate_owned(&compiled, json!({})).unwrap();
assert_eq!(result, json!([3, 4, 5]));
use datalogic_rs::DataLogic;
use serde_json::json;
let engine = DataLogic::new();
let logic = json!({ "cat": ["Hello, ", { "var": "name" }, "!"] });
let compiled = engine.compile(&logic).unwrap();
let result = engine.evaluate_owned(&compiled, json!({ "name": "World" })).unwrap();
assert_eq!(result, json!("Hello, World!"));
use datalogic_rs::DataLogic;
use serde_json::json;
let engine = DataLogic::new();
let logic = json!({ "max": [{ "var": "scores" }] });
let compiled = engine.compile(&logic).unwrap();
let result = engine.evaluate_owned(&compiled, json!({ "scores": [10, 20, 15] })).unwrap();
assert_eq!(result, json!(20));
Extend the engine with your own logic:
use datalogic_rs::{DataLogic, Operator, ContextStack, Evaluator, Result, Error};
use serde_json::{json, Value};
struct DoubleOperator;
impl Operator for DoubleOperator {
fn evaluate(
&self,
args: &[Value],
_context: &mut ContextStack,
_evaluator: &dyn Evaluator,
) -> Result<Value> {
match args.first().and_then(|v| v.as_f64()) {
Some(n) => Ok(json!(n * 2.0)),
None => Err(Error::InvalidArguments("Expected number".to_string()))
}
}
}
let mut engine = DataLogic::new();
engine.add_operator("double".to_string(), Box::new(DoubleOperator));
let result = engine.evaluate_json(r#"{ "double": 21 }"#, r#"{}"#).unwrap();
assert_eq!(result, json!(42.0));
use datalogic_rs::DataLogic;
use serde_json::json;
let engine = DataLogic::new();
let logic = json!({ "var": "user.address.city" });
let data = json!({
"user": {
"address": {
"city": "New York"
}
}
});
let compiled = engine.compile(&logic).unwrap();
let result = engine.evaluate_owned(&compiled, data).unwrap();
assert_eq!(result, json!("New York"));
let logic = json!({
"try": [
{ "/": [10, { "var": "divisor" }] },
0 // Default value on error
]
});
Works seamlessly with async runtimes:
use datalogic_rs::DataLogic;
use serde_json::json;
use std::sync::Arc;
#[tokio::main]
async fn main() {
let engine = Arc::new(DataLogic::new());
let logic = json!({ "*": [{ "var": "x" }, 2] });
let compiled = engine.compile(&logic).unwrap();
let handle = tokio::task::spawn_blocking(move || {
engine.evaluate_owned(&compiled, json!({ "x": 5 }))
});
let result = handle.await.unwrap().unwrap();
assert_eq!(result, json!(10));
}
{
"and": [
{ "==": [{ "var": "user.country" }, "US"] },
{ "or": [
{ "==": [{ "var": "user.role" }, "beta_tester"] },
{ ">=": [{ "var": "user.account_age_days" }, 30] }
] }
]
}
{
"if": [
{ ">=": [{ "var": "cart.total" }, 100] },
{ "-": [{ "var": "cart.total" }, { "*": [{ "var": "cart.total" }, 0.1] }] },
{ "var": "cart.total" }
]
}
{
"or": [
{ "and": [
{ "!=": [{ "var": "transaction.billing_country" }, { "var": "user.country" }] },
{ ">=": [{ "var": "transaction.amount" }, 1000] }
] },
{ ">=": [{ "var": "transaction.attempts_last_hour" }, 5] }
]
}
Over 50 built-in operators, including:
Category | Operators |
---|---|
Comparison | == , === , != , !== , > , >= , < , <= |
Logic | and , or , ! , !! |
Arithmetic | + , - , * , / , % , min , max , abs , ceil , floor |
Control Flow | if , ?: (ternary), ?? (coalesce) |
Arrays | map , filter , reduce , all , some , none , merge , in , length , slice , sort |
Strings | cat , substr , starts_with , ends_with , upper , lower , trim , split |
Data Access | var , val , exists , missing , missing_some |
DateTime | datetime , timestamp , now , parse_date , format_date , date_diff |
Type | type (returns type name as string) |
Error Handling | throw , try |
Special | preserve (for structured object preservation) |
Custom | User-defined operators via Operator trait |
Compilation Phase: JSON logic is parsed and compiled into a CompiledLogic
structure with:
Evaluation Phase: The compiled logic is evaluated against data with:
Created by Plasmatic, building open-source tools for financial infrastructure and data processing.
Check out our other projects:
Licensed under Apache 2.0. See LICENSE for details.