如何在Joi自定义验证函数的错误消息中添加有效取值?
问题
我尝试在Joi Schema中通过自定义验证函数检查字符串是否属于指定数组,但自定义验证的错误消息无法像内置.valid()方法那样显示有效取值列表。示例代码如下:
const Joi = require("joi"); const allowed = ["admin", "user", "noob"]; const method = (value, helpers) => { if (!allowed.includes(value)) { return helpers.error("any.only", {allowed}); } return value; }; const createProfileSchema = Joi.object().keys({ username: Joi.string().required().custom(method), text: Joi.string().valid("a", "b") }); const { error, value } = createProfileSchema.validate({ username: "asfd" , text: "c" }, { abortEarly: false }); console.log(error || value);
执行后输出的错误信息为:
[Error [ValidationError]: "username" must be one of . "text" must be one of [a, b]] { _original: { username: 'asfd', text: 'c' }, details: [ { message: '"username" must be one of ', path: [Array], type: 'any.only', context: [Object] }, { message: '"text" must be one of [a, b]', path: [Array], type: 'any.only', context: [Object] } ] }
可见username字段的错误消息缺少有效取值列表,如何实现让自定义验证的错误消息也显示[admin, user, noob],使完整错误消息为"username" must be one of [admin, user, noob]?
解决方案
问题出在调用helpers.error()时传递的上下文参数格式不对,Joi的any.only错误期望接收名为valids的数组参数,而非allowed。修改自定义验证函数的参数传递即可解决:
const Joi = require("joi"); const allowed = ["admin", "user", "noob"]; const method = (value, helpers) => { if (!allowed.includes(value)) { // 将参数名从allowed改为valids return helpers.error("any.only", { valids: allowed }); } return value; }; const createProfileSchema = Joi.object().keys({ username: Joi.string().required().custom(method), text: Joi.string().valid("a", "b") }); const { error, value } = createProfileSchema.validate({ username: "asfd" , text: "c" }, { abortEarly: false }); console.log(error || value);
修改后执行,username字段的错误消息会正确显示:
[Error [ValidationError]: "username" must be one of [admin, user, noob]. "text" must be one of [a, b]] { _original: { username: 'asfd', text: 'c' }, details: [ { message: '"username" must be one of [admin, user, noob]', path: [ 'username' ], type: 'any.only', context: { valids: [ 'admin', 'user', 'noob' ], value: 'asfd', label: 'username', key: 'username' } }, { message: '"text" must be one of [a, b]', path: [ 'text' ], type: 'any.only', context: { valids: [ 'a', 'b' ], value: 'c', label: 'text', key: 'text' } } ] }
补充说明
Joi内置的any.only错误模板会读取上下文对象中的valids数组生成错误消息,之前传递的allowed不是Joi预期的键名,因此无法正确渲染有效取值列表。只要将自定义错误的上下文参数改为valids并传入允许的数组,就能和内置.valid()方法生成一致格式的错误消息。
内容的提问来源于stack exchange,提问作者Marc
相关产品推荐
相关产品推荐

