目录

MoonGuard

MoonBit 原生的 JSON 解析与 Zod 风格 Schema 数据校验库

MoonGuard 是一个零依赖的 MoonBit 库,把「解析 JSON」和「校验数据结构」合并成一条流水线:从一段 JSON 文本出发,经过解析、结构校验、默认值填充,得到一个可以放心使用的值,或者一份带精确路径定位的问题清单。

适用场景:配置文件加载与校验、API 请求 / 响应体校验、表单数据校验、以及任何”外部输入不可信”的边界处理。

特性

  • 零依赖:核心功能全部使用 MoonBit 实现,仅依赖标准库
  • 完整的 JSON 解析器:字符串转义(含 \uXXXX 与代理对)、科学计数法、嵌套结构,错误带行列定位
  • Zod 风格的 Schema 组合str / num / obj / arr / union / nullable / recursive 等构造函数自由组合
  • 丰富的内置约束:字符串长度与格式(email / url / uuid / ipv4 / date)、数值范围与整数约束、数组长度、对象必填 / 可选 / 默认值 / 严格模式
  • 精确的错误报告$.user.tags[2] 形式的路径 + 稳定错误码 + 可读消息,一次校验收集全部问题而非遇错即停
  • 默认值填充:校验结果是一个新值,缺失的可选字段可按声明自动补全
  • 确定性序列化:紧凑 / 美化两种输出,方便做快照测试

安装

moon add hua1104/moonguard

然后在需要使用的包的 moon.pkg.json 中引入:

{
  "import": ["hua1104/moonguard"]
}

快速上手

// 1. 定义 Schema
let project = @moonguard.obj([
  @moonguard.field("name", @moonguard.str(min_len=1)),
  @moonguard.field("stars", @moonguard.num(min=0.0, integer=true)),
  @moonguard.field("tags", @moonguard.arr(@moonguard.str(), min_items=1)),
  @moonguard.opt_field("homepage", @moonguard.str(format="url")),
  @moonguard.field_or("license", @moonguard.str(), @moonguard.v_str("MIT")),
])

// 2. 解析 + 校验一步完成
let text = "{\"name\": \"MoonBit\", \"stars\": 10000, \"tags\": [\"wasm\"]}"
match project.validate_json(text) {
  Ok(v) => println(v.stringify(indent=2))   // license 已按默认值填充
  Err(issues) => for issue in issues { println(issue.to_string()) }
}

校验失败时的输出形如:

$.name: expected at least 1 characters, got 0 [min_length]
$.stars: expected an integer value [not_integer]
$.tags: expected at least 1 items, got 0 [min_items]
$.homepage: expected a valid url [format]

API 一览

解析与序列化

API 说明
parse(text) 解析 JSON 文本,返回 Result[Value, ParseError]
Value::stringify(indent?) 序列化;indent=2 输出美化格式
v_null() / v_bool / v_num / v_str / v_arr / v_obj 手动构造 Value
Value::as_str / as_num / as_bool / as_arr / as_obj 类型化取值(返回 Option)
Value::get_key / get_index 按键 / 下标访问子值
Value::equals 深度相等(对象忽略键顺序)
Value::type_name 值的 JSON 类型名

Schema 构造

API 说明
str(min_len?, max_len?, format?) 字符串;format 支持 email url uuid ipv4 date
num(min?, max?, integer?) / int_num(min?, max?) 数值 / 整数
boolean() / null_() / literal(v) 布尔 / null / 字面量
arr(elem, min_items?, max_items?) 数组,逐元素校验
tuple(items) 定长数组,逐位置校验
obj(fields, allow_extra?) 对象;allow_extra=false 拒绝未声明的键
field / opt_field / field_or 必填 / 可选 / 带默认值字段
map_of(values, min_size?, max_size?) 字典(任意键,统一值类型)
union(options) 联合:匹配任一候选即可
nullable(inner) 接受 null 或内层类型
refine(base, predicate, code, message) 自定义谓词精化
recursive(make) 递归 / 自引用结构

执行校验

API 说明
Schema::validate(value) 校验 Value,返回 Result[Value, Array[Issue]]
Schema::validate_json(text) 解析 + 校验一步完成
Schema::is_valid(value) 只关心是否合法
Issue 单条问题:path + code + messageto_string() 渲染为一行
path_to_string(path) 渲染 $.a[0].b 形式路径

错误码

type_mismatch min_length max_length format unknown_format min max not_integer min_items max_items tuple_arity missing_field unknown_field min_size max_size union_mismatch literal_mismatch parse_error 以及 refine 的自定义码。错误码是稳定 API,可用于程序化处理(如 i18n)。

运行示例与测试

moon test          # 运行全部测试
moon run src/examples   # 运行示例工程

功能边界

以下是有意为之的设计边界,便于使用者准确预期:

  • JSON 数值统一以 Double 表示(与 JavaScript 一致),不提供任意精度数值
  • 解析器接受标准 JSON;宽松扩展(注释、尾逗号等)计划以选项形式在后续版本提供
  • integer 约束在 Int 可精确表示的范围内判断,绝对值超过 2^52 的浮点数视为整数
  • 字符串格式校验器采用注释中写明的实用规则子集,不追求覆盖 RFC 全部边缘情况
  • 字符串长度约束按 Unicode 字符(码点)计数,而非 UTF-16 码元
  • 对象重复键遵循”后者覆盖前者”

项目结构

src/
  value.mbt       # Value 数据模型与序列化
  parser.mbt      # JSON 解析器
  issue.mbt       # 错误路径与问题报告
  formats.mbt     # 字符串格式校验器
  schema.mbt      # Schema 类型与构造函数
  validate.mbt    # 校验引擎
  *_test.mbt      # 黑盒测试
  examples/       # 可运行示例

路线图

  • JSON5 / 宽松解析选项(注释、尾逗号)
  • 类型安全解码:Schema 到 MoonBit 结构体的映射
  • 错误消息 i18n(中文消息包)
  • 更多格式校验器(ipv6、时间、duration、语义化版本)
  • JSON Schema(draft 2020-12)子集的导入 / 导出
  • 流式 / 增量解析

许可证

MIT

致谢

Schema API 的设计参考了 Zod(TypeScript)的使用体验,但本库为独立实现,未移植其代码。

关于
56.0 KB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

版权所有:中国计算机学会技术支持:开源发展技术委员会
京ICP备13000930号-9 京公网安备 11010802047560号