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

如何基于数据条件实现带子Schema的AJV自定义关键字验证

实现AJV自定义条件选择子Schema的关键字

核心思路

直接用AJV的addKeyword方法注册自定义关键字,在关键字的验证逻辑里根据数据的特定条件(比如示例中n的奇偶性)动态选择对应的子Schema执行验证,替代原生oneOf+discriminator的生硬逻辑,避免返回一堆无关错误。

完整实现代码

const Ajv = require('ajv');
const ajv = new Ajv();

// 注册自定义关键字,这里命名为conditionalSchema
ajv.addKeyword('conditionalSchema', {
  type: 'object',
  // 验证逻辑函数,参数为关键字配置、待验证数据等
  validate: function (schemaConfig, data) {
    // 根据数据条件匹配对应的子Schema
    let targetSchema;
    if (data.n % 2 === 0) {
      targetSchema = schemaConfig.even;
    } else {
      targetSchema = schemaConfig.odd;
    }

    // 编译并验证选中的子Schema
    const validateSub = ajv.compile(targetSchema);
    const isValid = validateSub(data);
    
    // 把子Schema的验证错误挂载到当前上下文
    if (!isValid) {
      this.errors = validateSub.errors;
      return false;
    }
    return true;
  }
});

// 定义验证Schema
const mySchema = {
  "type": "object",
  "properties": {
    "n": {"type": "number"}
  },
  "required": ["n"],
  "conditionalSchema": {
    "even": {
      "properties": {
        "p": {"type": "string"}
      },
      "required": ["p"]
    },
    "odd": {
      "properties": {
        "p": {"type": "number"}
      },
      "required": ["p"]
    }
  }
};

// 编译Schema并测试
const validate = ajv.compile(mySchema);

// 测试用例1:偶数n对应字符串p
const data1 = {n: 2, p: "test"};
console.log(validate(data1), validate.errors); // true, null

// 测试用例2:奇数n对应数字p
const data2 = {n: 3, p: 123};
console.log(validate(data2), validate.errors); // true, null

// 测试用例3:偶数n但p是数字,返回对应错误
const data3 = {n: 4, p: 567};
console.log(validate(data3), validate.errors); 
// false, [{instancePath: '/p', message: 'must be string', ...}]

针对oneOf场景的适配说明

如果你的实际场景是把分支Schema放在oneOf数组里,只需修改自定义关键字的逻辑:给每个oneOf子Schema加自定义匹配字段(比如matchCondition),然后在验证逻辑里遍历oneOf数组,找到符合条件的子Schema单独验证,这样就不会像原生oneOf那样返回所有不匹配的错误,只会输出选中Schema的验证问题。

内容的提问来源于stack exchange,提问作者MattBas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 04:00:06