Sign in

    jsonlogic

    Portable JSONLogic evaluation, scoped analysis, batch execution and native QueryX integration

    jsonlogic
    rules
    interpreter
    queryx
    Download zip
    Version
    0.2.1
    License
    MIT
    Last updated
    7 days ago
    Downloads
    11

    #MoonBit JSONLogic:跨端规则执行与应用接入库

    Check

    本项目让应用在 MoonBit 中执行已有的 JSONLogic 业务规则。规则以 JSON 保存和传递,同一份规则可用于动态表单、订单计算、集合筛选和后端条件查询。

    提供 JSONLogic 求值库、规则分析、批量执行 API/CLI、JavaScript/Wasm GC SDK 与 native QueryX/foxql 适配器。求值库支持内置操作、短路求值、集合局部作用域、日志捕获、结构化错误和执行预算,并在 native、JavaScript、Wasm、Wasm GC 四后端对照验证。Form.io 示例把真实表单的显示条件、计算值与校验交给 MoonBit 执行。查询模块在明确的字段类型和非空约束下生成现有 QueryX 表达式,复用 foxql 输出参数化 SQL。

    This project executes existing JSONLogic business rules in MoonBit across native, JavaScript, Wasm and Wasm GC targets. It includes scoped rule analysis, budgeted batch execution, a source-built JS/Wasm GC SDK and actual Form.io integration. The native QueryX/foxql adapter imports typed filter rules into the existing query pipeline and is checked against PostgreSQL results.

    #浏览器表单演示

    moon update npm ci npm run build:browser npm run serve:browser

    打开终端显示的本地地址(默认 http://127.0.0.1:4175/)。修改年龄查看字段显隐,修改数量和单价查看金额重算,输入 MOON 或错误校验码查看验证结果。切换 JavaScript/Wasm GC 后端或点击“运行接入验证”。这是 Form.io 5.6.1 实际渲染器,规则求值由编译后的 MoonBit 完成;不回退到原 JavaScript 求值器。

    SDK、类型声明、表单接入支持范围与验证命令见 SDK 与 Form.io。规则分析和批量执行见 分析与批量 API。

    #目标用户与应用接入

    面向使用 JSONLogic 保存业务配置、希望在 MoonBit 中复用规则的应用。开发者可以调用求值 API 实现表单条件、订单计算和集合处理;受约束的筛选规则还可以进入已有的查询生态。

    应用流程:

    JSONLogic 规则 + JSON 数据 → MoonBit JSONLogic 求值库 → 业务结果、日志或结构化错误

    查询模块面向已有 JSONLogic 筛选规则目录、希望在 MoonBit 后端继续复用配置查询数据库的应用。React Query Builder 支持生成 JSONLogic,提供可验证的规则来源;它也支持 SQL 等导出格式。数据库接入流程:

    存量 JSONLogic 筛选规则 + 服务端字段与类型约束 → 导入与语义检查 → QueryX Expr → 复用 foxql 生成参数化 SQL → 数据库返回匹配记录

    导入模块对类型不匹配、动态变量和无法保持语义的规则返回 JSON Pointer 与原因。固定 RQB 导出规则在原版 JavaScript、MoonBit JSONLogic、本地 QueryX 和 PostgreSQL 中得到相同的匹配记录 ID;完整求值库的兼容用例另行维护。

    #验证实际接入

    需要 MoonBit、Node.js、Python 与 psql,以及可连接的 PostgreSQL 服务。查询构建器仅是开发验证依赖。

    moon update npm ci --prefix tools/queryx-fixtures node tools/queryx-fixtures/generate.mjs --check python3 tools/check_queryx.py

    连接信息使用标准 PGHOST、PGPORT、PGUSER、PGPASSWORD、PGDATABASE 环境变量;未指定数据库时使用 postgres。验证只创建临时表并回滚事务。

    • 9 个未修改的 React Query Builder 8.24.3 导出规则,96 次记录求值:四条执行路径的匹配 ID 一致。
    • 18 个规则拒绝与 8 个输入拒绝用例:验证错误种类、规则/数据位置和原因。
    • 负向验证:故意修改 SQL 参数,确认实际数据库结果差异会被发现。
    • 16 项适配器单元测试:包含反向比较、严格区间边界、Int32 范围和输入预算。

    每次运行在 output/queryx/ 保存规则来源、SQL、类型化参数、逐项结果、拒绝诊断和负控报告。当前验证使用 PostgreSQL 17;数据集与支持范围见 接入文档。

    #项目范围

    部分用途
    src/JSONLogic 求值库;供应用安装与调用
    src/queryx/native JSONLogic 筛选规则导入与记录校验
    src/analysis/、src/batch/作用域/依赖分析与带预算的规则集执行
    src/cli/native JSON 批量请求 CLI
    src/interop/、sdk/编译导出、JS/Wasm GC 加载器及 TypeScript 声明
    examples/browser/真实 Form.io 表单与浏览器演示
    src/examples/queryx/调用实际 QueryX/foxql 的 native 接入程序
    compat/、tools/、tests/与原版 JavaScript 对照的回归验证;不进入应用运行路径
    docs/queryx-integration.md查询接入约定、复现方法和扩展范围

    JSONLogic 核心包与 compat 对照程序只导入 MoonBit 标准库。查询适配包依赖 QueryX 0.2.1/foxql 0.1.3,仅支持 native。根模块固定 moonbitlang/x@0.5.5 以兼容当前编译器;适配器不修改下载的依赖源码。Python、Node.js 和 PostgreSQL 用于接入验证。

    #与相邻工具的边界

    工具已有能力本项目的补充方向
    QueryX自定义 JSON 筛选格式、表达式求值、字段解析和 foxql 桥接将标准 JSONLogic 的受约束筛选子集导入其现有 Expr
    foxqlSQL 查询构建复用其 SQL 输出,提供 JSONLogic 导入与语义拒绝报告
    mbel、moon_cel 等表达式库使用其他表达式或规则标准,具备相似的规则求值用途直接接受 JSONLogic 规则对象,按其 truthiness、类型转换、短路和集合作用域执行,并给出固定版本语义对照
    json-logic-js在 JavaScript 中执行 JSONLogic已实现 MoonBit 求值与固定版本对照,并作为查询接入的独立参考

    项目以 JSONLogic 规则格式和执行语义为兼容目标;相似表达式工具之间仍有应用场景交集。查询模块负责有类型约束和语义拒绝的 JSONLogic 导入,字段解析与 SQL 查询构建复用 QueryX/foxql。求值库的 兼容范围与查询适配范围分别记录。

    #JSONLogic:可传递的业务规则

    {"and": [ {">=": [{"var": "age"}, 18]}, {"==": [{"var": "country"}, "CN"]} ]}

    这份规则搭配 {"age": 22, "country": "CN"} 得到 true。规则可存入配置、经 API 传递,再由不同端执行;无需为每条业务规则生成一段源代码。

    #接入验证场景

    • 用户人群筛选:导入年龄、状态和启用条件,通过现有查询管线返回匹配用户 ID。
    • 订单记录查询:导入状态与金额条件,复用字段映射并核对四条执行路径的匹配订单 ID。
    • 导入阻塞报告:遇到隐式类型转换、动态变量或集合规则,报告 JSON Pointer 和拒绝原因,保留原始配置以便修订。

    接入限定顶层非空 Int32/字符串/布尔字段。Int32 支持比较,字符串和布尔值支持同类型相等/不等;逻辑组合非空且各叶节点均为比较。缺失值、NULL、类型转换、动态路径、默认值、集合和字符串排序均拒绝。PostgreSQL 文本列使用 COLLATE "C",SQL 类型与字段声明一致。

    #JSONLogic 求值库:快速运行

    需要 MoonBit 工具链;完整 SDK/表单验证另需 Node.js 24+ 和 Python 3.10+。Node 22 可以运行 JS,但缺少当前 Wasm GC SDK 的字符串导入支持。已验证的工具链为 MoonBit CLI 0.1.20260920 / moonc v0.10.14+7d59c7ec9。

    git clone https://github.com/kaigeliang/moonbit-jsonlogic.git cd moonbit-jsonlogic moon update moon run src/examples/form --target native moon run src/examples/order --target js moon run src/examples/filter --target wasm-gc

    三个基础求值示例分别输出:

    {"show_company":true,"missing_required":["company"]} {"subtotal":110,"discount_percent":10} ["Ming"]

    示例代码:表单 · 订单 · 集合筛选。每个示例均断言预期结果;查询接入由独立的 native 程序与上述 PostgreSQL 验证命令演示。

    #在你的 MoonBit 项目中使用

    Mooncakes 0.2.1 提供求值、规则分析、批量 API 和 native 查询适配器;旧版 0.1.0 只有求值内核。JS/Wasm GC SDK 可从源码构建,或生成可安装的本地/CI 压缩包,见 SDK 安装方法。尚未发布到 npm registry。在你的 MoonBit 项目中运行:

    moon add kaigeliang/jsonlogic@0.2.1

    也可以通过源码 workspace 使用。例如把本仓库和你的 app 放在同一父目录,在 app/moon.mod 中加入:

    import { "kaigeliang/jsonlogic@0.2.1" }

    在 app/moon.work 中加入两个成员:

    members = [".", "../moonbit-jsonlogic"]

    在调用包的 moon.pkg 中导入:

    import { "kaigeliang/jsonlogic" @logic }

    fn main raise {
    let rule : Json = { ">=": [{ "var": "age" }, 18] }
    let result = @logic.apply(rule, { "age": 22 })
    assert_eq(result, true)
    }

    apply_json(rule_text, data_text) 接受两个 JSON 文本;evaluate(rule, data, max_steps=..., max_depth=...) 返回结果、捕获的 log 内容与已消耗步数。详见 API 与集成说明。

    #支持的操作

    类别操作
    数据var、missing、missing_some
    条件if、?:、and、or、!、!!
    比较==、!=、===、!==、>、>=、<、<=
    数值+、-、*、/、%、min、max
    字符串与集合cat、substr、in、merge、map、filter、reduce、all、some、none
    调试log(捕获到返回值)

    遵循 JSONLogic 的空数组假值、短路求值、集合局部作用域和 JavaScript 风格类型转换。非有限数、JavaScript 原型属性和自定义操作等边界见 兼容范围。通过已有用例不代表覆盖了所有 JavaScript 行为。

    #兼容性验证

    moon test --target native python3 tools/check_compat.py

    兼容性脚本执行固定版本的原版 JavaScript,将每个 MoonBit 后端的结果与原版逐项比较:

    • 278 个官方用例 + 37 个边界用例,当前共 315 个。
    • 四个后端均使用同一组输入,采用严格比较,不启用数值容差。
    • 每次运行保存输入版本对应的观察结果与差异报告到 output/compat/。
    • 故意篡改一个结果的负向验证,确认比较器会拒绝错误输出。

    72 项 MoonBit 单元测试覆盖求值(14)、查询适配(16,仅 native)、规则分析(26)和批量执行(16);各后端运行其支持的测试。Python 测试检查比较器拒绝差异、CLI 的退出码和输入失败路径。外部应用接入测试验证独立应用能够调用公共 API。

    #仓库内容

    src/ JSONLogic 运行库与单元测试 src/queryx/ native 筛选规则接入适配器与单元测试 src/analysis/ 全分支静态分析、作用域与字段依赖 src/batch/、src/cli/ 带预算的规则集 API 与 native CLI src/interop/、sdk/ JS/Wasm GC JSON ABI、加载器与类型声明 examples/browser/ Form.io 实际表单演示 src/examples/ 基础求值示例与 native 查询接入程序 compat/ 跨实现、跨后端的验证程序 tests/ 边界输入 fixtures tools/ 原版执行器、fixture 生成器、兼容性检查 third_party/ 固定版本的原版 JS、官方测试与许可证 docs/ 基础 API、兼容性说明与查询接入约定

    修改 fixtures 后执行 python3 tools/generate_cases.py && moon fmt。CI 会检查 fixtures、公共 API、各后端单元测试、示例、兼容结果及比较器失败路径。

    #SDK 与应用接入验证

    npm ci npm run check:types npm run build:sdk npm run check:sdk npm run check:formio npm run bundle:sdk npm run check:bundle npm run build:browser npx --no-install playwright install chromium npm run check:browser python3 -m unittest discover -s tests -p 'test_*.py' -v

    SDK 在 JS/Wasm GC 下各对照 315 个固定用例;压缩包在仓库外离线安装后再次验证两后端与类型声明。Form.io 实际渲染器的调用与原版 JavaScript 逐项对照,并将捕获的规则/数据在 native 中重放。Chromium 检查真实键盘输入、字段显隐、金额重算、校验、后端切换及输入保留;报告与截图保存到 output/sdk/、output/sdk-dist/、output/playwright/。

    Form.io 接入只支持预检过的标准 JSONLogic 子集,拒绝 _sum、getDate 等框架扩展、脚本和集合规则。静态分析保留动态路径的不确定性,不证明类型或执行成功;批量预算对失败条目保守计费。完整边界见对应文档。

    #许可证与来源

    JSONLogic 采用 MIT 许可证。

    • JSONLogic:MoonBit 移植参考 Jeremy Wadhams 的 json-logic-js;标准规则格式及原版操作语义归于上游。原版代码和官方测试保留 MIT 许可证;固定提交、文件校验值及来源见 来源记录。
    • 查询生态:QueryX 0.2.1 和 foxql 0.1.3 来自 Jared Zhou 的 moonbase,采用 Apache-2.0;其表达式与 SQL 桥接能力归于上游。React Query Builder 8.24.3 仅用于产生开发 fixtures,来源与版本记录在 fixture 和 npm 锁文件中。
    • 表单与开发验证:Form.io @formio/js 5.6.1 使用 MIT;esbuild、jsdom、TypeScript 为开发依赖,Playwright CLI 使用 Apache-2.0。版本固定在 npm 锁文件;表单 schema、SDK 和适配逻辑由本项目提供。

    LogicError

    pub(all) suberror LogicError {
    InvalidRule(String, String)
    LimitExceeded(String)
    NonFiniteNumber(String)
    InvalidInput(String)
    }

    Errors include a JSON Pointer into the rule whenever evaluation is involved.

    LogicError::to_string

    fn LogicError::to_string(self : LogicError) -> String

    Render an evaluation failure with its rule location.

    Evaluation

    pub(all) struct Evaluation {
    value : Json
    logs : Array[Json]
    steps_used : Int
    }

    The value and captured log operations from one evaluation.

    apply

    fn apply(rule : Json, data : Json) -> Json raise LogicError

    Evaluate a JSONLogic rule. See evaluate for log capture and execution budgets.

    apply_json

    fn apply_json(rule : String, data : String) -> Json raise LogicError

    Parse two JSON documents and evaluate. Parse failures are distinct from rule errors.

    evaluate

    fn evaluate(rule : Json, data : Json, max_steps? : Int, max_depth? : Int) -> Evaluation raise LogicError

    Evaluate a rule with bounded input traversal and execution. Logs are captured, not printed.

    truthy

    fn truthy(value : Json) -> Bool

    JSONLogic considers the empty array false and the string "0" true.