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

如何在JSON Schema中基于同层级category属性动态校验subcategory的枚举范围?

动态关联分类与子分类的JSON Schema校验方案(Node.js环境)

针对你遇到的「分类规模大,不想用大量if-else实现分类与子分类的关联校验」问题,我推荐使用ajv这个Node.js下最流行的JSON Schema验证库来解决,它支持动态生成Schema,完美适配你的场景。

核心思路

既然每个子分类仅属于一个主分类,我们可以先构建「分类-子分类」的映射关系,再基于这个映射动态生成JSON Schema的约束规则,避免手动编写大量重复的if-else逻辑。

具体实现步骤

1. 安装依赖

首先安装ajv:

npm install ajv

2. 构建分类-子分类映射

利用你已有的getCategories()和getSubcategories(category)函数,先同步(或异步)获取并构建映射关系:

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

// 构建分类与子分类的映射表
const categorySubMap = {};
const categories = getCategories(); // 假设是同步函数,异步场景看后面补充
categories.forEach(category => {
  categorySubMap[category] = getSubcategories(category);
});

3. 动态生成JSON Schema

我们会生成一个包含oneOf关键字的Schema,oneOf数组中的每个元素对应一个分类的约束(指定该分类下允许的子分类),全程自动生成,无需手动维护:

// 动态生成每个分类对应的约束规则
const categoryConstraints = Object.entries(categorySubMap).map(([category, subcategories]) => ({
  properties: {
    category: { const: category }, // 固定当前分类
    subcategory: { enum: subcategories } // 仅允许该分类下的子分类
  }
}));

// 完整的JSON Schema
const schema = {
  type: "array",
  items: {
    type: "object",
    properties: {
      category: { 
        type: "string", 
        enum: Object.keys(categorySubMap) // 约束分类必须是合法值
      },
      subcategory: { type: "string" }
    },
    required: ["category", "subcategory"], // 必填字段
    oneOf: categoryConstraints // 确保分类与子分类的组合合法
  }
};

4. 编译并验证数据

用ajv编译Schema后,就可以对目标JSON进行校验了:

// 编译验证器
const validate = ajv.compile(schema);

// 测试示例数据
const validData = [
  { category: "A", subcategory: "A1" },
  { category: "B", subcategory: "B2" }
];
const invalidData = [
  { category: "A", subcategory: "B1" } // 子分类不属于A,会校验失败
];

console.log(validate(validData)); // 输出: true
console.log(validate(invalidData)); // 输出: false
console.log(validate.errors); // 会详细提示错误原因,比如subcategory不在A的允许列表中

异步场景适配

如果你的getCategories()或getSubcategories(category)是异步函数(比如从数据库/API获取数据),只需要用async/await调整代码即可:

async function createValidator() {
  const Ajv = require('ajv');
  const ajv = new Ajv();

  // 异步获取分类列表
  const categories = await getCategories();
  const categorySubMap = {};
  
  // 异步获取每个分类的子分类
  for (const category of categories) {
    categorySubMap[category] = await getSubcategories(category);
  }

  // 后续生成Schema、编译验证器的逻辑和同步场景一致
  const categoryConstraints = Object.entries(categorySubMap).map(([cat, subs]) => ({
    properties: { category: { const: cat }, subcategory: { enum: subs } }
  }));

  const schema = { /* 同同步场景的Schema */ };
  return ajv.compile(schema);
}

// 使用验证器
createValidator().then(validate => {
  const testData = [{ category: "A", subcategory: "A2" }];
  console.log(validate(testData)); // 输出: true
});

方案优势

  • 无需手动维护大量if-else:不管分类数量增加多少,只要你的getCategories()和getSubcategories()能正确返回数据,代码无需修改。
  • 性能优异:ajv编译后的验证器执行效率极高,适合大规模数据校验。
  • 错误提示清晰:校验失败时会返回详细的错误信息,便于定位问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 12:02:39