假设我有一个具有四个可能属性的对象:a、b、c、d。 a 和 b 只能一起出现(即,当且仅当 b 出现时,a 才出现)。如果a和b出现,c不能出现(即a/b和c互斥)。如果 a 和 b 不出现,c 可能会出现(但不是必须)。 d 可以与 a/b、c 任意组合出现,也可以单独出现。除 a、b、c 或 d 之外,不得出现任何属性。
如何将其表达为 jsonschema?我怀疑我可以使用
oneOf
和 required
的某种组合,但我无法找出正确的咒语。
您可以将您的约束表述为:
"a"
和 "b"
都存在,并且 "c"
不存在"a"
和 "b"
均不存在。 ("c"
可能存在也可能不存在)第二点说“都不是”有点啰嗦。 在这里,我们使用
allOf
/not
来表达它。 (注意:您不能将它们分解为单个 required
子句,因为每个子句都需要一个单独的 not
。)
{
"oneOf": [
{
"required": ["a", "b"],
"not": {"required": ["c"]}
},
{
"allOf": [
{
"not": {"required": ["a"]}
},
{
"not": {"required": ["b"]}
}
]
}
]
}
替代结构
还有另一种说法“都不是”,其实就是再次使用
oneOf
。 由于您必须通过 oneOf
子句中的 恰好一个,因此如果其中一个条目是
{}
(通过所有内容),则所有其他选项都将被禁止。
虽然它稍微简洁一些,但阅读起来可能稍微不太直观:
{
"oneOf": [
{
"required": ["a", "b"],
"not": {"required": ["c"]}
},
{
"oneOf": [
{},
{"required": ["a"]},
{"required": ["b"]}
]
}
]
}
另一种选择是使用模式依赖项声明:
"dependencies": {
"c": {
"allOf": [
{
"not": { "required": [ "a" ] }
},
{
"not": { "required": [ "b" ] }
}
]
},
"a": {
"allOf": [
{
"not": { "required": [ "c" ] }
},
{
"required": [ "b" ]
}
]
},
"b": {
"allOf": [
{
"not": { "required": [ "c" ] }
},
{
"required": [ "a" ]
}
]
}
}
其他答案仍然有效,但在 JSON Schema 草案 7 中,有一种更清晰(尽管仍然很冗长)的方法来使用
if/then
来表达互斥属性。 if
模式针对实例进行测试,如果验证有效,则 then
模式也必须验证。因此,例如,如果您想让 before
和 after
属性互斥,您可以使用以下内容:
{
"if": { "required": ["before"] },
"then": {
"not": {
"required": ["after"]
}
}
}
由于在您的示例中,
c
与a
和b
互斥,因此逻辑(只是勉强)更复杂:
{
"if": {
"anyOf": [
{"required": ["a"]},
{"required": ["b"]}
]
},
"then": {
"required": ["a", "b"],
"not": {
"required": ["c"]
}
}
}
您可以将其解释为指定 如果指定了 a 或 b,则必须指定 a 和 b,并且不得指定 c。