根据 JSON 架构中的其他 属性 值设置其他属性
Setting additional properties based on other property values in JSON schema
我想根据现有 属性 的值设置筛选项的一些属性。如果 属性 Type
的值为 Range
,则应将属性 From
和 To
添加到 filterItem。否则其余的属性应该是 FilterValues
的数组。我尝试使用 if 和 else 设置属性,但似乎缺少某些东西。
我的 JSON 架构的部分:
"Filter": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/filterItem"
},
"additionalProperties": false
}
___________________________________________________
"filterItem": {
"type": "object",
"properties": {
"AttributeCode": {
"type": "string",
"pattern": "^[a-z0-9_-]+$"
},
"Typ": {
"type": "string"
},
"if": {
"properties": {
"Typ": {
"const": "Range"
}
}
},
"then": {
"properties": {
"From": {
"type": "integer",
"minLength": 1
},
"To": {
"type": "integer",
"minLength": 1
}
},
"additionalProperties": false
},
"else": {
"properties": {
"FilterValues": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z0-9_-]+$"
}
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
验证器显示属性不符合我的架构(屏幕截图):
validator
您的架构存在两个主要问题,您如何使用 if
-then
-else
以及如何使用 addtionalProperties
.
if
-then
-else
JSON 架构关键字只能出现在架构上下文中。 properties
定义一个对象,其值为模式。 properties
本身不是架构。
"properties": {
"foo": { ... }
"if": { ... },
"then": { ... }
}
这没有定义 属性、"foo" 加上条件。它定义了三个属性:"foo"、"if"、"then"。您需要将条件提高一个级别才能被验证器识别。
"properties": {
"foo": { ... }
},
"if": { ... }
"then": { ... }
否则,您正在正确使用 if
-then
-else
。只是放错地方了。
additionalProperties
一旦您将 if
-then
-else
放在正确的位置,您会发现出现了一堆 additionalProperties
错误。 additionalProperties
只能考虑架构中同一位置的 properties
和 patternProperties
关键字。
{
"allOf": [
{
"properties": {
"foo": { ... }
}
},
{
"properties": {
"bar": { ... }
},
"additionalProperties": false
}
]
}
/allOf/1/additionalProperties
只能兼顾/allOf/1/properties
,不能兼顾/allOf/0/properties
。因此,{ "foo": 1, "bar": 2 }
将无效,因为 "foo" 未在 /allOf/1/properties
.
中定义
有几种方法可以解决这个问题。首选方法是不使用 additionalProperties
。忽略其他属性而不是禁止它们。这最适合可演化的模式,但根据领域的不同,它并不总是可行的。
要有效地使用 additionalProperties
,您需要在同一个 properties
关键字下使用所有可能的 属性 名称。
"properties": {
"foo": { ... },
"bar": { ... }
},
"required": ["foo"],
"additionalProperties": false,
"if": {
"properties": {
"foo": { "const": 1 }
},
"required": ["foo"]
},
"then": { "required": ["bar"] }
这是一种可能的方法。 "bar" 仅在 "foo" 为 1 时才需要,但 "bar" 定义在顶部并且仅在条件通过时才需要。这不仅使 additionalProperties
像您预期的那样工作,而且更易于阅读,因为所有 属性 定义都在一个地方并且条件模式最少。
此时您可能担心当 "foo" 不是 1 时包含 "bar" 不会引发错误。同样,如果您的域允许,我鼓励您忽略额外的 属性 而不是禁止它。但是,如果你真的需要,你可以使用 else
来禁止额外的字段。
"else": { "not": { "required": ["bar"] } }
注意不要被该架构中的单词混淆。这并不意味着 "not required" 听起来像 "optional",而是 "forbidden".
我想根据现有 属性 的值设置筛选项的一些属性。如果 属性 Type
的值为 Range
,则应将属性 From
和 To
添加到 filterItem。否则其余的属性应该是 FilterValues
的数组。我尝试使用 if 和 else 设置属性,但似乎缺少某些东西。
我的 JSON 架构的部分:
"Filter": {
"type": [
"array",
"null"
],
"items": {
"$ref": "#/definitions/filterItem"
},
"additionalProperties": false
}
___________________________________________________
"filterItem": {
"type": "object",
"properties": {
"AttributeCode": {
"type": "string",
"pattern": "^[a-z0-9_-]+$"
},
"Typ": {
"type": "string"
},
"if": {
"properties": {
"Typ": {
"const": "Range"
}
}
},
"then": {
"properties": {
"From": {
"type": "integer",
"minLength": 1
},
"To": {
"type": "integer",
"minLength": 1
}
},
"additionalProperties": false
},
"else": {
"properties": {
"FilterValues": {
"type": "array",
"items": {
"type": "string",
"pattern": "^[a-z0-9_-]+$"
}
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
验证器显示属性不符合我的架构(屏幕截图): validator
您的架构存在两个主要问题,您如何使用 if
-then
-else
以及如何使用 addtionalProperties
.
if
-then
-else
JSON 架构关键字只能出现在架构上下文中。 properties
定义一个对象,其值为模式。 properties
本身不是架构。
"properties": {
"foo": { ... }
"if": { ... },
"then": { ... }
}
这没有定义 属性、"foo" 加上条件。它定义了三个属性:"foo"、"if"、"then"。您需要将条件提高一个级别才能被验证器识别。
"properties": {
"foo": { ... }
},
"if": { ... }
"then": { ... }
否则,您正在正确使用 if
-then
-else
。只是放错地方了。
additionalProperties
一旦您将 if
-then
-else
放在正确的位置,您会发现出现了一堆 additionalProperties
错误。 additionalProperties
只能考虑架构中同一位置的 properties
和 patternProperties
关键字。
{
"allOf": [
{
"properties": {
"foo": { ... }
}
},
{
"properties": {
"bar": { ... }
},
"additionalProperties": false
}
]
}
/allOf/1/additionalProperties
只能兼顾/allOf/1/properties
,不能兼顾/allOf/0/properties
。因此,{ "foo": 1, "bar": 2 }
将无效,因为 "foo" 未在 /allOf/1/properties
.
有几种方法可以解决这个问题。首选方法是不使用 additionalProperties
。忽略其他属性而不是禁止它们。这最适合可演化的模式,但根据领域的不同,它并不总是可行的。
要有效地使用 additionalProperties
,您需要在同一个 properties
关键字下使用所有可能的 属性 名称。
"properties": {
"foo": { ... },
"bar": { ... }
},
"required": ["foo"],
"additionalProperties": false,
"if": {
"properties": {
"foo": { "const": 1 }
},
"required": ["foo"]
},
"then": { "required": ["bar"] }
这是一种可能的方法。 "bar" 仅在 "foo" 为 1 时才需要,但 "bar" 定义在顶部并且仅在条件通过时才需要。这不仅使 additionalProperties
像您预期的那样工作,而且更易于阅读,因为所有 属性 定义都在一个地方并且条件模式最少。
此时您可能担心当 "foo" 不是 1 时包含 "bar" 不会引发错误。同样,如果您的域允许,我鼓励您忽略额外的 属性 而不是禁止它。但是,如果你真的需要,你可以使用 else
来禁止额外的字段。
"else": { "not": { "required": ["bar"] } }
注意不要被该架构中的单词混淆。这并不意味着 "not required" 听起来像 "optional",而是 "forbidden".