如何在JSON Schema的patternProperties中基于嵌套vpc_access限制子网名称长度
问题
我有一个以子网名称为键的subnets映射,想要创建JSON Schema,根据子网中嵌套的vpc_access字段值,条件性地限制子网名称的长度。我知道可以通过properties.PROPERTY1.properties.PROPERTY2.const.VALUE对嵌套属性设置条件,但因为用了patternProperties没法确定具体属性名,尝试了以下YAML格式的JSON Schema,想确认这个实现是否可行,同时寻求正确的方法:
subnets: if: patternProperties: ^.*$: properties: vpc_access: const: true required: - vpc_access then: propertyNames: pattern: ^[a-z][a-z0-9-]{1,22}[a-z0-9]$ patternProperties: ^.*$: $ref: /schemas/network.subnet
解答
你当前的写法不可行,核心问题是if条件的逻辑偏差:你的规则会要求所有子网的vpc_access都为true时,才会触发then里的名称长度限制,但实际需求应该是只要某个子网的vpc_access为true,该子网的名称就需要符合长度规则,两者逻辑完全不符。
正确实现思路
要实现「单个子网的vpc_access为true时,对应子网名称需符合特定格式」的需求,需要把条件判断和名称约束绑定到每个子网条目的键值关联上,以下是两种可行方案:
方案一:使用$data扩展(推荐,需实现支持)
如果你的JSON Schema实现支持$data关键字(比如Ajv),可以直接引用当前键对应的值的vpc_access字段,写法简洁直观:
subnets: type: object # 保留基础子网schema引用 patternProperties: ^.*$: $ref: /schemas/network.subnet # 对属性名称(子网名称)添加条件约束 propertyNames: if: # 引用当前键对应的值的vpc_access字段,判断其是否为true $data: 0/vpc_access const: true then: # 符合条件时,子网名称必须匹配该正则 pattern: ^[a-z][a-z0-9-]{1,22}[a-z0-9]$
方案二:标准JSON Schema实现(不依赖扩展)
如果无法使用$data扩展,可以通过allOf+not组合实现逻辑,写法稍繁琐但符合标准规范:
subnets: type: object allOf: # 规则1:vpc_access为true的子网,名称必须符合指定格式 - patternProperties: ^[a-z][a-z0-9-]{1,22}[a-z0-9]$: properties: vpc_access: const: true required: - vpc_access # 规则2:所有子网都需符合基础子网schema - patternProperties: ^.*$: $ref: /schemas/network.subnet # 规则3:禁止存在「名称不符合格式但vpc_access为true」的子网 - not: patternProperties: # 匹配不符合名称规则的键 ^(?!([a-z][a-z0-9-]{1,22}[a-z0-9])$).*$: properties: vpc_access: const: true required: - vpc_access
总结
原写法的逻辑错误在于对整个subnets对象做统一条件判断,而非针对单个子网的键值对。优先选择支持$data的方案,若受限于环境则使用标准JSON Schema的组合规则实现。
内容的提问来源于stack exchange,提问作者gorge511
相关产品推荐
相关产品推荐

