基于if子句的JSON Schema验证:按template值匹配parameters属性
问题:根据模板值动态验证parameters属性的JSON Schema编写
我需要为如下YAML结构编写JSON Schema验证:
stages: - template: template-a.yml parameters: a-param1: abc a-param2: xy - template: template-b.yml parameters: b-param1: df b-param2: yz需求是根据
template属性的值,让parameters对象拥有对应的不同属性。我尝试了如下Schema,但其中的if/then规则对对象属性不生效(仅当属性与template同层级时有效):
{ "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/azure-templates", "definitions": { "azure-templates": { "type": "object", "additionalProperties": false, "properties": { "stages": { "type": "array", "items": { "anyOf": [ { "$ref": "#/definitions/template-select" } ] } } }, "required": [ "stages" ], "title": "azure-pipeline" }, "template-params-a": { "if": { "properties": { "template": { "const": "template-a.yml" } }, "required": [ "template" ] }, "then": { "properties": { "parameters": { "type": "object", "additionalProperties": false, "properties": { "a-param1": { "type": "string" }, "a-param2": { "type": "string" } } } } } }, "template-params-b": { "if": { "properties": { "template": { "const": "template-b.yml" } }, "required": [ "template" ] }, "then": { "properties": { "parameters": { "type": "object", "additionalProperties": false, "properties": { "b-param1": { "type": "string" }, "b-param2": { "type": "string" } } } } } }, "template-select": { "type": "object", "additionalProperties": false, "properties": { "template": { "enum": [ "template-a.yml", "template-b.yml" ] } }, "allOf": [ { "$ref": "#/definitions/template-params-a", "$ref": "#/definitions/template-params-b" } ], "required": [ "template" ], "title": "Template" } } }
修正后的Schema及说明
你的Schema有两个核心问题:
template-select里的additionalProperties: false会直接拒绝parameters属性,因为初始properties里只定义了template,没有声明parameters的存在allOf数组里的对象重复使用$ref键,JSON Schema会忽略重复的键,最终只有最后一个$ref生效,导致template-params-a的规则完全没起作用
以下是修正后的Schema:
{ "$schema": "http://json-schema.org/draft-07/schema#", "$ref": "#/definitions/azure-templates", "definitions": { "azure-templates": { "type": "object", "additionalProperties": false, "properties": { "stages": { "type": "array", "items": { "$ref": "#/definitions/template-select" } } }, "required": ["stages"], "title": "azure-pipeline" }, "template-a-params": { "type": "object", "additionalProperties": false, "properties": { "a-param1": {"type": "string"}, "a-param2": {"type": "string"} }, "required": ["a-param1", "a-param2"] }, "template-b-params": { "type": "object", "additionalProperties": false, "properties": { "b-param1": {"type": "string"}, "b-param2": {"type": "string"} }, "required": ["b-param1", "b-param2"] }, "template-select": { "type": "object", "additionalProperties": false, "properties": { "template": { "enum": ["template-a.yml", "template-b.yml"] }, "parameters": {} }, "required": ["template"], "allOf": [ { "if": {"properties": {"template": {"const": "template-a.yml"}}}, "then": {"properties": {"parameters": {"$ref": "#/definitions/template-a-params"}}} }, { "if": {"properties": {"template": {"const": "template-b.yml"}}}, "then": {"properties": {"parameters": {"$ref": "#/definitions/template-b-params"}}} } ], "title": "Template" } } }
关键修改点:
- 在
template-select的properties里先声明parameters为任意类型,避免被additionalProperties: false拒绝 - 将if/then规则直接整合到
allOf的数组项中,每个规则单独成为一个对象,确保所有规则都能生效 - 把参数结构抽成独立的定义,让Schema更清晰
- 给每个参数集合加上
required,确保必填参数不缺失(如果不需要必填可以去掉)
内容的提问来源于stack exchange,提问作者Kai Goerlich
相关产品推荐
相关产品推荐

