我试图为JSON对象创建一个模式,该模式根据其属性之一的值而变化:type
.
:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["INT", "PERCENT"]
}
},
"required": ["type"],
"allOf": [
{
"if": {
"properties": {"type": {"const": "INT"}}
},
"then": {
"properties": {
"value": {"type": "number", "multipleOf": 1}
},
"required": ["value"],
"additionalProperties": false
}
},
{
"if": {
"properties": {"type": {"const": "PERCENT"}}
},
"then": {
"properties": {
"value": {"type": "number"},
"min": {"type": "number"},
"max": {"type": "number"}
},
"required": ["value", "min", "max"],
"additionalProperties": false
}
}
]
}
但是我从我正在尝试的各种验证器中得到各种各样的错误行为。
//
:
{
"type": "PERCENT", // property type has not been defined(?!)
"value": 0.0,
"min": 10,
"max": 25
}
{
"type": "INT", // no errors allowed, and value
"value": 0.1, // should've been flagged as not multiple of 1
"min": 10, // should've been flagged as disallowed additional property
"max": 25 // same as above
}
这是我正在尝试的验证器
提前感谢您的帮助!
似乎你已经发现问题是addtionalProperties
只考虑在它定义的子模式中定义的属性。这就是为什么你必须包含"类型"财产在你的then
。你有几个选项是对你发布的不满意的解决方案的改进。
选项1:unevaluatedProperties
草案2019-09引入unevaluatedProperties
关键字。如果您在模式的顶层使用它,而不在任何地方使用addtionalProperties
,那么您将从additionalProperties
获得您所期望的行为。我看到你使用的是draft-07,所以你必须升级才能使用这个解决方案。
选项2:Boolean模式
你想出的解决方案是重新定义"类型"。属性在then
模式中。additionalProperties
只需要"type"要声明,您不需要再次包含它的模式。您可以使用true
或空模式{}
。
选项3:propertyNames
可以用propertyNames
代替additionalProperties
。这允许您声明对象中允许的属性名列表,而不是用true
或{}
破解additionalProperties
,以确定允许的属性名。
我找到了一种方法来得到我想要的,但这并不意味着我喜欢它。必须重新定义"类型"我觉得不太对。
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["INT", "PERCENT"]
}
},
"required": ["type"],
"allOf": [
{
"if": {
"properties": {"type": {"const": "INT"}}
},
"then": {
"properties": {
"value": {"type": "number", "multipleOf": 1},
"type": {"type": "string"}
},
"required": ["value", "type"],
"additionalProperties": false
}
},
{
"if": {
"properties": {"type": {"const": "PERCENT"}}
},
"then": {
"properties": {
"value": {"type": "number"},
"min": {"type": "number"},
"max": {"type": "number"},
"type": {"type": "string"}
},
"required": ["value", "min", "max", "type"],
"additionalProperties": false
}
}
]
}
测试……
这验证:
{
"type": "PERCENT",
"value": 0,
"min": 10,
"max": 20
}
{
"type": "INT",
"value": 0
}
这个错误在我想要的方式:
{
"type": "INT",
"value": 0.1, // not a multiple of 1
"min": 4, // not expected
"max": 5 // not expected
}
{
"type": "PERCENT",
"value": 0.1,
"max": 5 // min is a required property
}