如何基于preference对象用Joi实现接口请求的动态条件验证?
基于Joi实现动态条件验证的方案
问题背景
现有如下偏好配置对象:
const preference = { INVENTORY: { id: true, part_name: true, part_number: true, is_available: false }, ASSET: { name: true, type: true, make: false }, DRIVERS: { driver_name: true, license_number: true, experience: false } };
我们有一个更新接口,接收的JSON请求体必须包含preference_type字段(值只能是INVENTORY、ASSET或DRIVERS),其余字段需要根据传入的preference_type动态确定:
- 当
preference_type为INVENTORY时,合法请求体示例:
{ "section": "INVENTORY", "id": false, "part_name": false, "part_number": true, "is_available": true }
- 当
preference_type为DRIVERS时,合法请求体示例:
{ "section": "DRIVERS", "driver_name": true, "license_number": false, "experience": false }
- 当
preference_type为ASSET时,合法请求体示例:
{ "section": "ASSET", "name": false, "type": true, "make": false }
如何基于上述preference对象,通过Joi动态实现这种条件验证?
解决方案
可以利用Joi的when()条件验证方法,结合动态生成的Schema规则来实现,具体步骤如下:
1. 生成各类型的字段验证规则
从preference对象中提取每个类型对应的字段,为每个字段生成boolean类型的必填验证规则:
const Joi = require('joi'); // 动态生成各section对应的字段验证Schema const sectionSchemas = {}; Object.entries(preference).forEach(([section, fields]) => { const fieldRules = {}; Object.keys(fields).forEach(field => { fieldRules[field] = Joi.boolean().required(); }); sectionSchemas[section] = Joi.object(fieldRules); });
2. 构建主验证Schema
使用when()方法根据preference_type的值动态匹配对应的字段规则,同时确保preference_type和section的合法性与一致性:
const updatePreferenceSchema = Joi.object({ preference_type: Joi.string() .valid(...Object.keys(preference)) .required(), section: Joi.string() .valid(...Object.keys(preference)) .required() .valid(Joi.ref('preference_type')) // 强制section与preference_type值一致 }).when('preference_type', { switch: Object.entries(sectionSchemas).map(([section, schema]) => ({ is: section, then: schema })) });
3. 验证示例
用实际请求体测试验证逻辑:
// 合法的INVENTORY类型请求 const validInventoryReq = { preference_type: "INVENTORY", section: "INVENTORY", id: false, part_name: false, part_number: true, is_available: true }; const validResult = updatePreferenceSchema.validate(validInventoryReq); console.log(validResult.error); // 输出undefined,验证通过 // 非法请求:传入不属于当前类型的字段 const invalidReq = { preference_type: "ASSET", section: "ASSET", name: false, type: true, experience: false // ASSET类型不包含该字段,验证失败 }; const invalidResult = updatePreferenceSchema.validate(invalidReq); console.log(invalidResult.error.details[0].message); // 输出对应的错误提示
关键说明
- 通过遍历
preference对象动态生成规则,避免硬编码,后续新增类型只需修改配置对象即可同步验证逻辑。 - 用
Joi.ref('preference_type')确保section与preference_type值一致,防止参数不匹配。 when()的switch语法可批量处理多条件分支,对应不同类型应用不同的字段验证规则。
内容的提问来源于stack exchange,提问作者SunAns
相关产品推荐
相关产品推荐

