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

Joi中仅当指定字段填写时设某字段为必填的问题排查

问题分析与解决方案

你的schema核心问题在于when的条件逻辑错误:

  1. 未指定条件的作用范围:默认情况下when会将条件应用在two字段自身的值上,而非整个对象,完全偏离了你基于one和three字段状态判断的需求。
  2. 条件判断逻辑不符:用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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 16:34:54