如何在JS中根据数据解析JSON Schema条件并生成完整Schema?
问题描述
我有如下带条件约束的JSON Schema:
const oneOfConditional = [ { if: { properties: { type: { enum: ["numerical"], }, }, }, then: { properties: { op: { default: "=", enum: ["=", "<", ">", "<=", ">="], metadata: { labels: [ "is equal to", "is less than", "is greater than", "is less than or equal to", "is greater than or equal to", ], }, }, }, }, }, ] const allOfConditional = [ { if: { properties: { op: { enum: ["=", "!="], }, type: { enum: ["categorical"], }, }, }, then: { properties: { value: { type: "array", items: { type: "string", }, }, }, }, else: { properties: { value: { type: ["number", "string"], }, }, }, }, { if: { properties: { type: { enum: ["datetime"], }, }, }, then: { properties: { format: { type: "string", default: "YYYY-MM-DD", }, }, }, }, ] const complexSchema = { title: "Filters", type: "array", minItems: 0, maxItems: 100, items: { type: "object", required: ["column", "type"], oneOf: oneOfConditional, allOf: allOfConditional, properties: { type: { title: "Type", type: "string", enum: ["categorical", "datetime", "string", "numerical"], }, op: { title: "Operator", type: "string", }, conj: { title: "Conjunction", type: "string", default: "AND", enum: ["OR", "AND"], }, value: { title: "value", }, }, }, }
待验证的数据为:
[{type:"numerical", op:"", conj:"AND",value:null}]
我正在使用AJV做验证,但不仅需要验证错误结果,还需要得到解析所有条件约束后的完整Schema,期望得到的解析后Schema如下:
{ title: "Filters", type: "array", minItems: 0, maxItems: 100, items: { type: "object", required: ["column", "type"], properties: { type: { title: "Type", type: "string", enum: ["categorical", "datetime", "string", "numerical"], }, op: { default: "=", enum: ["=", "<", ">", "<=", ">="], metadata: { labels: [ "is equal to", "is less than", "is greater than", "is less than or equal to", "is greater than or equal to", ], }, }, conj: { title: "Conjunction", type: "string", default: "AND", enum: ["OR", "AND"], }, value: { title: "value", type: ["number", "string"], }, }, }, }
请问有没有可行的解决方案?
可行解决方案
方案1:手动匹配条件并合并Schema
AJV本身没有直接输出「解析后完整Schema」的API,可根据待验证数据手动匹配oneOf/allOf中的条件规则,将符合条件的then/else约束合并到基础Schema中:
- 匹配
oneOf条件:待验证数据的type为numerical,命中oneOfConditional规则,把then里的op属性约束合并到基础Schema的properties.op上。 - 匹配
allOf条件:第一条规则中数据type不是categorical,触发else分支,将value的类型约束["number", "string"]合并到基础Schema的properties.value;第二条规则中数据type不是datetime,不触发then分支,无需合并。 - 清理条件关键字:合并完成后移除原始Schema中的
oneOf、allOf关键字,得到最终完整Schema。
可以写工具函数自动化合并,核心逻辑是遍历条件数组,检查数据是否满足if条件,用对象合并工具(如lodash.merge)将约束合并到基础Schema的properties中。
方案2:利用AJV内部验证逻辑推导
AJV验证数据时会内部评估条件约束,可通过自定义插件或钩子记录触发的规则,再合并生成Schema:
- 注册AJV的
beforeValidate钩子,在验证前检查数据匹配的条件规则。 - 收集所有触发的
then/else约束。 - 验证完成后,将收集到的约束合并到基础Schema中,生成解析后的完整Schema。
这种方式和AJV实际验证逻辑完全一致,能确保合并的约束和验证规则匹配。
注意事项
- 合并时注意优先级:条件分支的约束优先级高于基础Schema定义。
- 若存在多个
oneOf规则同时命中(不符合oneOf的定义,但需处理异常情况),要解决约束冲突。 - 嵌套条件约束需递归处理合并逻辑。
内容的提问来源于stack exchange,提问作者san_anto
相关产品推荐
相关产品推荐

