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

如何基于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:13:11