JSON Schema条件验证:避免catalog间重复story属性
问题:确保story属性不同时出现在两个catalog中
我有一个包含catalogA和catalogB两个属性的JSON Schema,还有四个嵌套属性story1、story2、story3、story4。需要设置验证规则,保证任意一个story属性不能同时在两个catalog里定义,否则验证失败。我试过用not语法,但没达到预期效果。
有效JSON实例
{ "catalogA": [ { "story1": "xyz", "story2": "abc" } ], "catalogB": [ { "story3": "ddd", "story4": "ccc" } ] } // 此实例有效:story1/story2仅在catalogA,story3/story4仅在catalogB
无效JSON实例
{ "catalogA": [ { "story1": "xyz", "story2": "abc" } ], "catalogB": [ { "story1": "xyz", "story3": "ddd", "story4": "ccc" } ] } // 此实例无效:story1同时出现在catalogA和catalogB中
当前使用的Schema代码
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "catalogA": { "type": "array", "items": { "type": "object", "properties": { "story1": { "type": "string" }, "story2": { "type": "string" }, "story3": { "type": "string" }, "story4": { "type": "string" } } } }, "catalogB": { "type": "array", "items": { "type": "object", "properties": { "story1": { "type": "string", "not": {} }, "story2": { "type": "string", "not": {} }, "story3": { "type": "string", "not": {} }, "story4": { "type": "string", "not": {} } } } } } }
解决方案
你之前用的not: {}完全不起作用,因为空的not约束不会匹配任何值,等于没加限制。要实现跨catalog的冲突检查,必须在Schema的根层级添加全局验证规则——因为单个属性内部的规则无法直接引用另一个属性的内容。
核心思路:在根级别用not规则,检查是否存在某个story同时出现在catalogA和catalogB的items中。我们需要为每个story都定义这样的冲突检查,然后用anyOf把这些检查组合起来(只要触发其中一个冲突,验证就失败)。
修改后的Schema代码:
{ "$schema": "http://json-schema.org/draft-07/schema#", "type": "object", "properties": { "catalogA": { "type": "array", "items": { "type": "object", "properties": { "story1": { "type": "string" }, "story2": { "type": "string" }, "story3": { "type": "string" }, "story4": { "type": "string" } } } }, "catalogB": { "type": "array", "items": { "type": "object", "properties": { "story1": { "type": "string" }, "story2": { "type": "string" }, "story3": { "type": "string" }, "story4": { "type": "string" } } } } }, // 全局冲突检查:禁止任意story同时出现在两个catalog中 "not": { "anyOf": [ // 检查story1是否同时存在于两个catalog { "properties": { "catalogA": { "items": { "required": ["story1"] } }, "catalogB": { "items": { "required": ["story1"] } } }, "required": ["catalogA", "catalogB"] }, // 检查story2是否同时存在于两个catalog { "properties": { "catalogA": { "items": { "required": ["story2"] } }, "catalogB": { "items": { "required": ["story2"] } } }, "required": ["catalogA", "catalogB"] }, // 检查story3是否同时存在于两个catalog { "properties": { "catalogA": { "items": { "required": ["story3"] } }, "catalogB": { "items": { "required": ["story3"] } } }, "required": ["catalogA", "catalogB"] }, // 检查story4是否同时存在于两个catalog { "properties": { "catalogA": { "items": { "required": ["story4"] } }, "catalogB": { "items": { "required": ["story4"] } } }, "required": ["catalogA", "catalogB"] } ] } }
规则说明
- 根层级的
not:表示如果匹配到anyOf里的任意一种冲突情况,整个实例就验证失败。 - 每个
anyOf子项:检查对应的story是否同时被catalogA和catalogB的至少一个item包含(用required强制该story存在)。 required: ["catalogA", "catalogB"]:确保只有当两个catalog都存在时才进行冲突检查,避免其中一个catalog缺失时误判。
这样修改后,你的有效实例会通过验证,而包含重复story的无效实例会被拦截。
内容的提问来源于stack exchange,提问作者Oshie
相关产品推荐
相关产品推荐

