[英]JSON Schema oneof without required
在JSON Schema
草案 7 或 8 中,正确的说法是我们想要可选的属性之一而不是两者。 我可以用required
关键字构造,但是你必须包含其中一个必需的属性。 这是我能想到的,这是正确的吗?
在这个例子中,我试图验证field_1
是必需的,我们想要field_2
、 field_3
之一,或者都不想要。 (见例子)
{
"$schema": "http://json-schema.org/draft-08/schema#",
"type": "object",
"properties": {
"field_1": {
"type": "string"
},
"field_2": {
"type": "string"
},
"field_3": {
"type": "string"
}
},
"required": [
"field_1"
],
"oneof": [
{
"properties": [
"field_2"
]
},
{
"properties": [
"field_3"
]
}
],
"additionalProperties": false,
"examples": [
{
"field_1": "1",
"field_2": "2"
},
{
"field_1": "1",
"field_3": "3"
},
{
"field_1": "1"
}
]
}
我会添加一个带有嵌套allOf
的oneOf
:
{
...
"allOf": [
{
"oneOf": [
{"required": ["field_2"]},
{"required": ["field_3"]}
],
},
{
"not": {
"required": ["field_2", "field_3"]
}
}
],
...
}
这要求两个字段之一存在,但不能同时存在。
我认为这可以通过仅使用oneOf
进一步简化:
{
...
"oneOf": [
{"required": ["field_2"]},
{"required": ["field_3"]}
],
...
}
oneOf
失败。oneOf
会通过。oneOf
失败。是的,这更好。 看看你所拥有的,我认为这就是你想要做的,所以你真的很接近!
要在两个字段都不存在时通过,您需要第一个解决方案,但将allOf
更改为anyOf
:
{
...
"anyOf": [
{
"oneOf": [
{"required": ["field_2"]},
{"required": ["field_3"]}
],
},
{
"not": {
"required": ["field_2", "field_3"]
}
}
],
...
}
not
子模式将通过,并且anyOf
将通过。oneOf
子模式将通过,而anyOf
将通过。oneOf
子模式都将通过,因此oneOf
失败not
anyOf
失败了您可以在此处测试这些解决方案
这里有几个选项可以添加到@gregdennis 的答案中。
这是dependencies
关键字的一个很好的用例。 这就是说,“如果有一个“field_2”,就不可能有一个“field_3”,并且,“如果有一个“field_3”,就不可能有一个“field_2”。 如果“field_2”或“field_3”都不存在,则不应用任何约束并且架构通过。
"dependencies": {
"field_2": { "not": { "required": ["field_3"] } },
"field_3": { "not": { "required": ["field_2"] } }
}
这个有点老套,但它的好处是成为一个班轮。 如果需要“field_1”并且只允许“field_2”或“field_2”其中之一,则此对象中的属性不能超过两个。 当心,这个解决方案可能比它的价值更聪明。 由于此约束间接起作用,因此可能会导致将来的维护困难。
"maxProperties": 2
这只是dependencies
项选项的更详细版本,但对于阅读架构的人来说可能更具描述性。
"allOf": [
{
"if": { "required": ["field_2"] },
"then": { "not": { "required": ["field_3"] } }
},
{
"if": { "required": ["field_3"] },
"then": { "not": { "required": ["field_2"] } }
}
]
我不得不尝试为 3 个字段解决这个问题,其中字段 1 也是可选的。 这样做揭示了@gregdennis 对解决方案 3的回答比它需要的略多,这实现了相同的目标,因为不需要检查所需的单个值,因为两者都不需要。
{
...
"not": {
"required": ["field_2", "field_3"]
}
...
}
要为 3 执行此操作,它看起来像:
{
...
"not": {
"anyOf": [{
"required": ["field_1", "field_2", "field_3"]
},
{
"required": ["field_1", "field_2"]
},
{
"required": ["field_2", "field_3"]
},
{
"required": ["field_1", "field_3"]
}]
}
...
}
随着您添加更多字段,这显然变得不那么有用。 因此,有空间去 N 的更好解决方案如下:
{
...
"anyOf": [
{
"oneOf": [
{"required": ["field_1"]},
{"required": ["field_2"]},
{"required": ["field_3"]}
]
},
{
"not": {
"anyOf": [
{"required": ["field_1"]},
{"required": ["field_2"]},
{"required": ["field_3"]}
]
}
}
]
...
}
你可以在这里玩。
您可以按如下方式执行此操作:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"field_1": {
"type": "string"
}
},
"oneOf": [
{
"properties": {
},
"additionalProperties": false
},
{
"properties": {
"field_2": {
"type": "string"
}
},
"required": ["field_2"],
"additionalProperties": false
},
{
"properties": {
"field_3": {
"type": "string"
}
},
"required": ["field_3"],
"additionalProperties": false
}
],
"required": [
"field_1"
]
}
如本书所述:“oneOf: (XOR) 必须对其中一个子模式有效”。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.