JSON Schema 校验报 "required" 字段缺失,怎么定位修复?
现象:校验不通过,报错指向 required
你拿一段 JSON 去校验,Schema 返回类似:
{
"keyword": "required",
"message": "should have required property 'email'",
"missingProperty": "email"
}
意思是:Schema 要求必须有 email 字段,但你的数据里没有。听起来简单,但"明明写了却还报缺失"的情况很常见——根因往往不在「少写了一个字」,而在层级、$ref、或 oneOf 把报错信息藏起来了。
为什么"写了还报缺失"
1. 字段名拼错 / 大小写不一致
Schema 要的是 email,你数据里是 Email 或 e-mail——JSON 字段名区分大小写,差一个字符就算缺失。从 Excel 或别的语言反序列化来的数据最容易踩这个坑(如 Go 的 json:"eMail" tag、Python 的 snake_case)。肉眼比对两份长字段列表效率很低,用 JSON Diff 把"实际数据"和"一份已知合法的样例"对比,差异字段立刻现形。
2. 嵌套层级搞错
required 是针对它所在的那一层对象生效的。比如:
{
"type": "object",
"properties": {
"user": {
"type": "object",
"required": ["email"],
"properties": { "email": { "type": "string" } }
}
}
}
这里的 required: ["email"] 只约束 user 这个子对象,不约束顶层。如果你的 email 放在顶层,就会报缺失。报错信息里的路径(如 /user)就是按层级给的——先看路径再改数据,别急着全文件搜字段名。
3. 数组元素忘了包一层
数组里每个元素都要满足 items 里的 Schema。常见错误是给数组本身写 required,而不是给 items 里的对象写:
{
"type": "array",
"items": {
"type": "object",
"required": ["id"]
}
}
报错路径会带数组下标(如 /2 或 users.2.id),表示第三个元素缺 id——比"数组校验失败"这种粗粒度报错好用得多。
additionalProperties 的坑
如果你设了 "additionalProperties": false,那么任何 Schema 没声明的字段都会报错(不只是缺字段,多字段也错)。调试阶段建议先设成 true 或注释掉,定位完再收紧。
还有一个高频混淆点:required 写在 properties 里面是无效的——它必须作为对象的兄弟关键字与 properties 平级。Schema 校验器一般不报这个写法错误,它只是静默不生效,让人误以为"必填没起作用"。
oneOf 里的 required:报错经常不说「required」
当 required 写在 oneOf 某一分支里时,现代校验器常常只报「必须恰好匹配 oneOf 中的一个 schema」,而不会直接点名 missingProperty。诊断技巧:把各分支临时提到顶层分别校验,哪一条分支的错误列表突然变得可读,就是真凶。anyOf 更宽松(匹配一条即可),若有人为了「消掉报错」把 oneOf 改成 anyOf,往往只是关掉了原本想要的互斥。更稳妥的做法是保留 oneOf,并给每个分支加可区分字段(如 "type": "card" vs "type": "bank")。
$ref 与草稿版本:字段「要求」写在哪
通过 $ref 引用共享定义时,会原样继承该定义里的 required 数组——在 draft-07 里很难按引用点覆盖必填列表(2020-12 在 unevaluatedProperties 等方向上松了一点)。两个接口共用 $defs/user 却需要不同必填字段时,应拆定义,或用 allOf 在外层追加本接口的 required。报错定位可能指向被引用文件,而编辑器停在引用方——顺着 $ref 链看完再下结论。
若一份「以前能过」的 Schema 突然对每个字段都报缺失,先核对校验器识别的草稿版本:definitions → $defs 的路径没改时,引用解析成空,表现就像所有字段都不存在。
怎么用工具逐步定位
打开 ToolVault 工具匣 的 JSON Schema 校验工具:
- 左边贴 JSON 数据,右边贴 Schema;
- 点校验,工具会列出全部错误(
allErrors,不止第一个),并标出出错的字段路径; - 对照路径,检查是拼错、层级错还是类型错;
- 先用 JSON 格式化工具 把数据和 Schema 都格式化,层级一眼看清,避免看错嵌套;
- 修完后如果 Schema 本身也要跟着改,用 JSON Schema 编辑器 调整结构,或用 JSON Schema 生成器 从样例数据反向生成骨架。
三条减少「required 连环炸」的写法
- 排查阶段临时展开
$ref:间接层省行数、费工时;错误难读时先内联或加$id显式测解析。 - 给 oneOf 加判别字段:裸分支近匹配时失败信息含糊;必填的
type/kind能把「哪支失败」变成「这个字段不对」。 - 用样例文档钉住 Schema:每个变体留一份必须通过校验的 fixture,挂进 CI——Schema 静默腐化时,required 漂移往往正好在合作方联调那天才暴露。
诚实边界:浏览器内校验适合联调与教学;超大 Schema、远程 $ref 拉取、自定义 format 关键字,仍应以服务端/CI 中的同一套 Ajv(或等价实现)为准。本站工具做的是「同一份数据与 Schema、本地立刻看到全部错误路径」。
FAQ
多个 required 缺失,为什么只报一个?
严格的校验器可能遇到第一个就停;本站工具会列出全部错误,方便一次性改完。
type 不对也会报 required 吗?
不会。类型错误是 type 关键字报的(should be string),和 required 是两条独立的错误。看 keyword 字段就能区分。
能不能让某些字段"二选一必填"?
可以,用 oneOf 或 anyOf 包两组 required,比单纯 required 更灵活。例如"手机号和邮箱至少填一个":
{
"anyOf": [
{ "required": ["phone"] },
{ "required": ["email"] }
]
}
需要「恰好一种」时用 oneOf,并尽量加判别字段,避免错误信息只剩一句 oneOf 失败。
字段存在但值是 null,为什么还算"通过"?
required 只检查字段是否存在,不检查值。"email": null 能通过 required,但过不了 type: "string"。要同时禁止 null,把类型写成 "type": "string"(不要把 null 放进 type 联合),或显式 not: { "type": "null" };OpenAPI 场景再对照 nullable。
实现注记
定位 required 报错常用 diff 缩小范围,这里有个必须处理的边角:大整数解析用无损表示,同值时按数字原文判等、实例引用不等不算差异;若按引用比,数值相同的长 ID 也会被误报成修改,把排障带偏。
感谢阅读这篇 ToolVault 工具匣 技术文章。相关工具:JSON Schema 校验、JSON Schema 编辑器、JSON Schema 生成器、JSON 格式化、JSON Diff。访问 首页 查看更多开发者工具。
相关工具
相关文章
JSON 大整数精度陷阱:雪花 ID 被静默改写时怎么查
超过 2^53-1 的 JSON 数字经 JSON.parse 会尾部舍入。对照劣质格式化与无损路径,并互链 JWT/Base64 与站内 JSON 工具。
JSON 解析报错 Unexpected token?5 种常见原因和修复方法
JSON 解析报错 Unexpected token?本文总结 5 种最常见的 json 格式错误原因:尾逗号、单引号、未转义字符、BOM 头、注释,逐一给出修复方法和代码示例。
JSON 排错完全手册:从报错信息到修复(按症状速查)
JSON 报错看不懂?本手册按「症状 → 原因 → 修复」组织,覆盖语法错误、中文转义、编码乱码、Schema 校验失败四类高频问题,附诊断决策树与通用排查流程。