JSON Schema 校验
左边贴 schema,右边贴数据,逐条列出不匹配的路径和原因,改完立刻重新校验。
数据符合这份 schema 的结构约束。业务规则(数值范围、时间先后、关联记录是否存在)不在 schema 里,仍要在代码中检查。
- 2020-12 的 $dynamicRef、unevaluatedProperties 等关键字 Ajv 支持有限,复杂 schema 建议在服务端用对应 draft 的校验器复核。
- 校验只针对贴进来的这一份数据,不会代入 $data、远程 $ref 或自定义关键字。
校验规则
这里用 Ajv 校验:没写 $schema 时按 draft-07 编译,写了 2019-09 或 2020-12 就切换到对应的校验器。只会解析同一份文档里的 $ref,远程引用不会去取。schema 本身语法错误时,会直接给出编译失败的原因,不会拿一份坏 schema 去校验数据。
错误路径是 JSON Pointer,/items/0/name 表示 items 数组第一个元素的 name 字段,空字符串代表根节点。先看路径定位数据,再看关键字判断是类型问题还是约束问题。
format 默认不强制校验,邮箱、日期这类内容只检查是不是字符串。要生成 schema 用JSON 转 JSON Schema,要把 schema 变成 TypeScript 类型用JSON Schema 转 TypeScript,格式化数据用JSON 格式化。
常见问题
为什么格式校验没有生效?
format 在 JSON Schema 里默认是注解,不强制校验。这里没有引入 ajv-formats,所以 email、date-time 这类只会检查类型,不会检查内容是否符合格式。需要强校验时在服务端补上 format 插件。
additionalProperties: false 报了一堆错?
它表示只允许 properties 里声明过的字段。对象里多一个字段就会报错,常见于接口加了新字段但 schema 没同步。排查时先看错误里的 additionalProperty,再决定是补 schema 还是删数据。
支持 $ref 引用别的文件吗?
只支持同一份 schema 内部的 $ref(#/definitions/... 或 #/$defs/...)。远程 URL 和相对路径引用不会去解析,遇到时会报找不到引用。多文件 schema 建议先用工具打包成一份再校验。
为什么数字 1 能通过 integer 校验?
JSON Schema 的 integer 指数学意义上的整数,1.0 在 JSON 里解析后就是 1,和 JavaScript 的判断一致。要区分整数字面量,只能靠原始文本或自定义关键字。
draft-04 的 schema 能校验吗?
Ajv 默认按 draft-07 编译,draft-04 的 exclusiveMinimum 是布尔值,语义和后来的版本不同,可能报 schema 编译错误。老 schema 建议先升级到 draft-07 或 2020-12。
校验通过就能放心用了吗?
schema 只描述结构,不保证业务正确:金额是否为负、开始时间是否早于结束时间、ID 是否真的存在,这些都要在代码里另外校验。schema 是第一道门,不是全部。