You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 21:23:17