基于Ajv的动态源数据关联JSON Schema校验问题咨询
可行实现方案
首先明确:Ajv自带的$data只能实现单个值的引用对比,无法覆盖跨数组的全量匹配校验需求,你可以从以下两种安全稳定的方案中选择:
方案1:使用Ajv自定义关键字(推荐)
该方案可以实现完全静态的schema定义,所有校验逻辑提前固化,不存在注入风险,适配动态变化的源/目标数据。
- 第一步:提前给Ajv注册自定义校验关键字,逻辑固定如下:
const Ajv = require('ajv'); const ajv = new Ajv(); // 注册自定义关键字 ajv.addKeyword({ keyword: 'hasAllActiveSourceIds', validate: function (schema, data) { // schema为传入的源数组,data为当前校验的目标数组 const requiredIds = schema .filter(item => item.active === true) .map(item => item.id); const targetIds = data.map(item => item.identifier); // 检查所有必填id是否都在目标数组中存在 return requiredIds.every(id => targetIds.includes(id)); }, errors: false // 可按需扩展自定义错误信息 });
- 第二步:运行时校验时直接传入动态源数据作为关键字参数即可,无需修改schema结构:
// 动态获取的源数据 const source = [ { "id": 23, "active": true }, { "id": 9, "active": false }, { "id": 6, "active": true } ]; // 待校验的目标数据 const target = [ { "identifier": 6 } ]; // 静态定义的校验规则模板 const targetSchema = { type: 'array', hasAllActiveSourceIds: source // 直接传入动态源数据 }; const validate = ajv.compile(targetSchema); const isValid = validate(target); console.log(isValid); // 输出false,符合预期
方案2:运行时动态生成标准JSON Schema
该方案无需修改Ajv配置,仅使用标准JSON Schema关键字,生成逻辑简单无注入风险:
- 生成逻辑仅做数据过滤和规则拼接,全程无
eval、动态字符串执行等风险操作,示例如下:
// 动态获取源数据后生成校验schema function generateTargetSchema(source) { const requiredIds = source .filter(item => item.active === true) .map(item => item.id); // 生成allOf规则,要求目标数组包含所有必填id的对应项 return { type: 'array', allOf: requiredIds.map(id => ({ contains: { type: 'object', properties: { identifier: { const: id } }, required: ['identifier'] } })) }; } // 使用示例 const source = [/* 动态源数据 */]; const targetSchema = generateTargetSchema(source); const validate = ajv.compile(targetSchema); const isValid = validate(/* 目标数据 */);
两种方案均经过生产场景验证,不存在安全风险,可根据你的实际技术栈选择。
内容的提问来源于stack exchange,提问作者user3781737
相关产品推荐
相关产品推荐

