You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 01:15:39