Joi 17.6.0校验对象数组无法获取空/必填字段报错信息
Joi对象数组内部字段校验错误获取方案
使用依赖版本:Joi@^17.6.0
参考截图:
问题原因
无法获取locations数组内部对象字段的具体校验错误,通常由两个问题导致:
- 数组Schema定义不完整:仅声明了
locations为数组类型,没有通过.items()绑定数组内每个元素的校验规则,Joi不会深入校验数组内部的对象字段 - 校验配置和错误读取方式错误:默认配置下Joi遇到第一个错误就终止校验,且直接读取
error.message只能拿到顶层聚合的错误提示,无法定位到数组内具体索引的字段错误
具体解决步骤
1. 补全数组项的Schema定义
必须通过Joi.array().items()明确指定数组内每个对象的校验规则,需要非空校验的字段要显式加.empty()声明空值(空字符串、null、undefined)为无效值,否则Joi默认会将空字符串判定为合法值,不会触发必填校验。
示例代码:
const Joi = require('joi'); // 定义locations数组内单个位置项的校验规则,字段和规则对应业务配置即可 const locationItemSchema = Joi.object({ id: Joi.number().required().empty().messages({ 'any.required': '位置ID不能为空', 'number.base': '位置ID必须为数字类型' }), name: Joi.string().required().empty().messages({ 'any.required': '位置名称不能为空', 'string.empty': '位置名称不能为空白字符串' }) // 其余字段按业务需求补充对应校验规则 }); // 整体数据校验Schema const dataSchema = Joi.object({ // 其他字段的校验规则保持原有写法即可 locations: Joi.array() .items(locationItemSchema) // 关键:绑定数组项的校验规则 .required() .messages({ 'array.base': 'locations必须为数组格式', 'any.required': 'locations为必填字段' }) });
2. 校验时关闭提前终止配置
调用validate方法时传入abortEarly: false,让Joi收集所有校验错误,而不是遇到第一个错误就直接返回,否则数组靠后位置的错误会被漏掉。
const { error, value } = dataSchema.validate(待校验的JSON数据, { abortEarly: false, // 核心配置:收集全量错误 stripUnknown: true // 可选配置:自动剔除未在Schema中定义的字段 });
3. 遍历错误详情拿到具体字段报错
不要直接读取error.message,遍历error.details数组即可拿到每个错误的完整信息,包括数组内具体哪个索引的哪个字段出错:
if (error) { const formattedErrors = error.details.map(item => ({ // 错误字段路径,例:locations.0.name 代表locations数组第1项的name字段校验失败 fieldPath: item.path.join('.'), errMsg: item.message })); // formattedErrors里包含所有层级的错误,包括locations数组内部对象的字段错误 console.log(formattedErrors); }
常见踩坑
如果加了.items()规则后依然拿不到内部错误,检查是否给内部字段加了.optional()或者漏写了.required(),未标记为必填的字段Joi不会对空值做拦截。
内容的提问来源于stack exchange,提问作者Tarun Agarwal
相关产品推荐
相关产品推荐

