为何JSON Schema多元素条件验证仅单元素场景生效?
问题描述
我有如下JSON数据:
{ "inputs": [ { "term": { "units": "liters", "termType": "material" } }, { "term": { "units": "kilogram", "termType": "crop" } } ] }
需要验证的规则是:若inputs数组中任意元素的termType为material,则该元素的units必须为kilogram。
我编写了如下验证Schema:
{ "allOf": [ { "if": { "required": [ "inputs" ], "properties": { "inputs": { "items": { "properties": { "term": { "properties": { "termType": { "const": "material" } } } } } } } }, "then": { "properties": { "inputs": { "items": { "properties": { "term": { "properties": { "units": { "const": "kilogram" } } } } } } } } } ] }
使用ajv 6版本(启用draft 07)验证时,发现该规则仅在inputs数组仅包含单个material类型元素(如下所示)时会报错:
{ "inputs": [ { "term": { "units": "liters", "termType": "material" } } ] }
但在包含两个元素的初始示例中不会报错,请问这是为什么?
问题原因
你的Schema逻辑错误在于if条件的判断逻辑不符合预期:
- JSON Schema中,
items关键字默认要求数组的所有元素都匹配指定的schema。所以你的if条件实际表达的是:“当inputs数组的每一个元素的term.termType都是material时”,才会触发then的验证。 - 当inputs数组同时包含material和crop类型的元素时,if条件不满足(因为不是所有元素都是material),所以then分支不会执行,自然不会对units进行校验,也就不会报错。
- 只有当数组里全是material类型元素时,if条件才会触发,此时then要求所有元素的units都是kilogram,所以单个错误元素会触发报错。
正确的验证Schema
要实现“任意material类型的元素必须满足units为kilogram”的规则,应该直接对数组的每个元素使用if/then逻辑,而不是对整个数组做判断:
{ "properties": { "inputs": { "items": { "if": { "properties": { "term": { "properties": { "termType": { "const": "material" } }, "required": ["termType"] } }, "required": ["term"] }, "then": { "properties": { "term": { "properties": { "units": { "const": "kilogram" } }, "required": ["units"] } } } } } } }
这个Schema的逻辑是:对inputs数组中的每一个元素单独校验——如果该元素的term.termType是material,那么它的term.units必须是kilogram。不管数组里有没有其他类型的元素,只要有material类型元素不符合units要求,就会触发报错。
内容的提问来源于stack exchange,提问作者Guillaume
相关产品推荐
相关产品推荐

