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

基于JOI实现依赖其他字段的自定义表单验证求助

Joi实现依赖多字段的自定义验证规则

问题分析

你之前的尝试存在两个核心问题:

  • when示例只单独判断了email的空值,没结合mobile的状态,无法覆盖“email和mobile均为空”的场景
  • or示例仅检查字段是否存在且通过验证,但如果字段存在但值为空(比如email: ''),Joi会认为该字段验证通过,导致or逻辑不符合你“值不能为空”的实际需求

解决方案

以下是精准匹配需求的验证代码,同时实现**“email和mobile均空时username必填”和“username空时email/mobile至少一个有有效值”**的双向约束:

const joi = require('joi');

const validations = joi.object({
  username: joi.string()
    // 正向约束:当email和mobile都为空值时,username必填
    .when(joi.object({
      email: joi.valid('', null, undefined),
      mobile: joi.valid('', null, undefined)
    }), {
      is: joi.object().required(),
      then: joi.required().messages({
        'any.required': '当email和mobile均为空时,username为必填项'
      }),
      otherwise: joi.optional()
    }),
  // 定义email的实际验证规则,允许空值但可选
  email: joi.string().email().optional().allow('', null, undefined),
  // 定义mobile的实际验证规则(示例为国内手机号正则),允许空值但可选
  mobile: joi.string().pattern(/^1[3-9]\d{9}$/).optional().allow('', null, undefined)
})
// 反向约束:username为空时,email或mobile至少一个不为空
.or(
  joi.object({ username: joi.invalid('', null, undefined) }).unknown(),
  joi.object({ email: joi.invalid('', null, undefined) }).unknown(),
  joi.object({ mobile: joi.invalid('', null, undefined) }).unknown()
)
.options({ abortEarly: false });

关键逻辑说明

  1. 正向约束:

    • 通过joi.object()作为when的条件,同时校验email和mobile是否都为空值(包含空字符串、null、undefined)
    • 满足条件时强制username必填,否则保持可选
  2. 反向约束:

    • 用.or()组合三个条件:要么username有有效值,要么email有有效值,要么mobile有有效值
    • .unknown()确保其他字段不会干扰当前约束的判断
  3. 字段类型优化:

    • 替换joi.any()为对应字段的实际验证规则(比如邮箱格式、手机号正则),既提升验证精准度,也避免空值被误判为有效字段

测试验证

  • ✅ email和mobile均为空 → 必须填username,否则报错
  • ✅ username为空 → email或mobile至少一个填有效值,否则报错
  • ✅ username有值 → email和mobile可全空,验证通过
  • ✅ email/mobile有有效值 → username可空,验证通过

内容的提问来源于stack exchange,提问作者Mr.Singh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 11:52:14