如何用AJV依据其他字段验证minItems并实现多字段关联校验
如何根据mode字段值校验notify数组的minItems属性?
我使用AJV结合JSON Schema做对象校验,已实现以下规则:
- 当mode为1或2时,必填temperature字段
- 当mode为3时,必填temperature和humidity字段
现在需要新增规则:根据mode值校验notify数组的长度,但在notify的定义中添加if-else规则未生效。
当前可正常运行的Schema
{ type: 'object', required: [ 'notify', ], additionalProperties: true, properties: { notify: { type: 'array' }, mode: { type: 'number', enum: [0, 1, 2, 3] } }, if: { properties: { mode: { enum: [1, 2], }, }, }, then: { required: ['temperature'], }, else: { if: { properties: { mode: { const: 3, }, }, }, then: { required: ['temperature', 'humidity'], }, }, }
尝试修改但未生效的Schema
{ type: 'object', required: [ 'notify', ], additionalProperties: true, properties: { notify: { type: 'array', if: { properties: { mode: { enum: [1, 2], }, }, }, then: { minItems: 1, }, else: { minItems: 0, }, }, mode: { type: 'number', enum: [0, 1, 2, 3] } }, if: { properties: { mode: { enum: [1, 2], }, }, }, then: { required: ['temperature'], }, else: { if: { properties: { mode: { const: 3, }, }, }, then: { required: ['temperature', 'humidity'], }, }, }
问题原因
你之前在notify的子Schema中编写的if规则无效,因为此时校验上下文是notify数组本身,它并不包含mode属性,无法读取父对象的mode值进行判断。
解决方案
将notify的长度校验规则移到顶层的if-else结构中,和已有的必填字段规则合并,这样校验上下文是整个父对象,就能正确访问mode字段了。
修正后的完整Schema
{ type: 'object', required: ['notify'], additionalProperties: true, properties: { notify: { type: 'array' }, mode: { type: 'number', enum: [0, 1, 2, 3] }, temperature: { type: 'number' }, // 可选补充字段类型,提升校验严谨性 humidity: { type: 'number' } // 可选补充字段类型 }, // 处理mode为1或2的场景 if: { properties: { mode: { enum: [1, 2] } } }, then: { required: ['temperature'], properties: { notify: { minItems: 1 } // mode为1/2时,notify至少1个元素 } }, // 处理其他mode的分支 else: { // 处理mode为3的场景 if: { properties: { mode: { const: 3 } } }, then: { required: ['temperature', 'humidity'], properties: { notify: { minItems: 1 } // 可根据需求修改,比如mode=3时要求minItems=2 } }, // 处理mode为0的场景 else: { properties: { notify: { minItems: 0 } // mode为0时,notify允许为空数组 } } } }
关键说明
- 所有依赖父对象字段(如
mode)的校验逻辑,必须放在顶层if-else中,确保校验上下文是整个对象。 - 若不同mode需要不同的
notify长度规则,只需在对应then块中修改minItems或maxItems参数即可。
内容的提问来源于stack exchange,提问作者Chicky
相关产品推荐
相关产品推荐

