HapiJS/Joi:字段为字符串或指定键对象的验证及when报错问题
解决Joi验证title字段时的自引用
when规则报错问题 你碰到的AssertionError [ERR_ASSERTION]: Item cannot come after itself: title(title)报错,本质是因为Joi不允许在when规则里直接引用同一个字段作为判断条件,这会触发自引用的循环依赖检测,导致验证失败。
针对你的需求(title既可以是必填字符串,也可以是包含指定语言键的必填对象),这里有两种靠谱的解决方式:
方法1:用alternatives实现(推荐)
这种方式最贴合你的需求场景,代码也更直观易懂,完全避开自引用问题:
const schema = Joi.object({ title: Joi.alternatives() .try( // 第一种情况:必填字符串 Joi.string().required(), // 第二种情况:必填对象,其中en_US必填,lt_LT可选 Joi.object({ en_US: Joi.string().required(), lt_LT: Joi.string() }).required() ).required() });
alternatives().try()会依次尝试匹配传入的规则,只要满足其中任意一种格式,验证就会通过,完美适配你的业务场景。
方法2:修正when规则(避免自引用)
如果你一定要用when语法,可以通过引用当前对象的方式绕过自引用检测,不过这种写法不如第一种直观:
const schema = Joi.object({ title: Joi.any() .when(Joi.in('$'), { // 判断当前对象的title是否为字符串类型 is: Joi.object({ title: Joi.string() }), then: Joi.string().required(), otherwise: Joi.object({ en_US: Joi.string().required(), lt_LT: Joi.string() }).required() }).required() });
测试验证
你可以用这几个案例验证效果:
- 字符串格式:
schema.validate({ title: 'Chicken' })→ 验证通过 - 多语言对象格式:
schema.validate({ title: { en_US: 'Chicken', lt_LT: 'Vištiena' } })→ 验证通过 - 缺失必填语言键:
schema.validate({ title: { lt_LT: 'Vištiena' } })→ 因en_US缺失,验证失败
内容的提问来源于stack exchange,提问作者Combustible Pizza
相关产品推荐
相关产品推荐

