如何基于参数name取值匹配对应Joi Schema实现动态校验
现有实现问题排查
你的现有代码存在3个核心问题,无法符合需求:
- 规则映射完全错位:你当前的when分支对应关系和预设逻辑完全不符:
- 你将
contract-associate匹配了intern schema - 你将
intern-associate匹配了contractor schema
完全不符合你一开始定义的四类参数对应规则,会导致校验逻辑完全错误。
- 你将
- 字段引用路径错误:
params是和body同级的属性,你在body.work_information节点下直接写params.name,Joi会在当前节点的子路径下查找字段,无法正确获取name参数,必须修改为相对路径../params.name或者绝对路径/params.name。 - 冗余代码问题:
- 你预设的associate、intern schema里重复定义了两次
manager_information字段,属于无效冗余 - 外层body定义的
Job_title.required()和各个子schema中重复定义的同规则冲突,属于冗余代码 - 多分支
when的写法不符合Joi标准规范,部分低版本Joi不兼容该多参数传入的写法。
- 你预设的associate、intern schema里重复定义了两次
更优实现方案
第一步:优化预设Schema,抽离公共字段复用
首先先清理冗余代码,抽离所有类型共有的公共校验规则,减少重复代码:
// 抽离所有work_information共有的公共字段 const baseWorkInfo = Joi.object().keys({ Full_Name: Joi.string().required(), Email_Address: Joi.string().required(), phone_number: Joi.string().required() }) // 全职正式工校验规则 const associate = Joi.object().keys({ Job_title: Joi.string().required(), work_information: baseWorkInfo.keys({ company_Name: Joi.string().required(), manager_information: Joi.string().required(), gender: Joi.string().required(), Date_of_Birth: Joi.string().required() }) }) // 实习生校验规则 const intern = Joi.object().keys({ Job_title: Joi.string().required(), work_information: baseWorkInfo.keys({ company_Name: Joi.string().required(), manager_information: Joi.string().required(), gender: Joi.string().required(), Date_of_Birth: Joi.string().required(), university_name: Joi.string().required(), date_of_graduation: Joi.string().required() }) }) // 合同工校验规则 const contractor = Joi.object().keys({ Job_title: Joi.string().required(), work_information: baseWorkInfo.keys({ consulting_agency: Joi.string().required() }) }) // 季节工校验规则 const seasonal = Joi.object().keys({ Job_title: Joi.string().required(), work_information: baseWorkInfo.keys({ duration_of_employment: Joi.string().required(), manager_information: Joi.string().required() }) })
第二步:修正主校验Schema逻辑
使用Joi标准的switch分支写法,修正路径和映射关系:
const createAssociateProfile = Joi.object({ params: Joi.object({ name: Joi.string().valid('full-time', 'contract-associate', 'intern-associate', 'seasonal-associate').required() }), // 直接用when匹配整个body的规则,避免重复定义字段 body: Joi.object().required().when('params.name', { switch: [ { is: 'full-time', then: associate }, { is: 'contract-associate', then: contractor }, { is: 'intern-associate', then: intern }, { is: 'seasonal-associate', then: seasonal } ] }) })
可选优化点
如果你的Joi版本支持Joi.alternatives,也可以用条件匹配的写法实现更灵活的校验,逻辑可读性更高。
内容的提问来源于stack exchange,提问作者Pfizer
相关产品推荐
相关产品推荐

