Joi中仅当指定字段填写时设某字段为必填的问题排查
问题分析与解决方案
你的schema核心问题在于when的条件逻辑错误:
- 未指定条件的作用范围:默认情况下
when会将条件应用在two字段自身的值上,而非整个对象,完全偏离了你基于one和three字段状态判断的需求。 - 条件判断逻辑不符:用
Joi.required()作为子字段的条件,会要求one和three必须存在且符合类型,但你的one和three本身是可选字段,这种写法会导致逻辑判断混乱。
正确写法
要实现“仅当one和three均已填写时,two为必填”的逻辑,需要明确指定when的条件作用于根对象,并检查one和three的存在性:
const schema = Joi.object({ one: Joi.string(), two: Joi.string().when('$', { is: Joi.object({ one: Joi.exist(), three: Joi.exist() }), then: Joi.required() }), three: Joi.string() });
代码说明
'$'代表根对象,告诉Joi要基于整个对象的状态进行判断;Joi.exist()用于检查字段是否存在(即已填写,值不为undefined);- 当
one和three同时存在时,two触发必填规则,否则保持可选。
测试验证
// 空对象:通过,无错误 schema.validate({one: undefined, two: undefined, three: undefined}); // one和three都填写,two未填:返回ValidationError: "two" is required schema.validate({one: 'foo', three: 'bar', two: undefined}); // 仅one填写,two未填:通过 schema.validate({one: 'foo', two: undefined, three: undefined}); // 仅three填写,two未填:通过 schema.validate({one: undefined, two: undefined, three: 'bar'});
进阶:严格检查非空值
如果需要确保one和three不仅存在且为非空字符串,可以将Joi.exist()替换为Joi.string().required():
is: Joi.object({ one: Joi.string().required(), three: Joi.string().required() })
内容的提问来源于stack exchange,提问作者ali_o_kan
相关产品推荐
相关产品推荐

