I have a legacy API I'm trying to define in a JSON Schema and the object has a weird structure where there are a set of 4 properties, any one of them is required, and 3 of them are mutually exclusive. The are a more than 30 shared optional properties after that as well, I'll note them as ...
.
e.g.,
{ "foo": "bar", "baz": 1234, ... } // OK
{ "foo": "bar", "buzz": 1234, ... } // OK
{ "foo": "bar", "fizz": 1234, ... } // OK
{ "foo": 1234, ... } // OK
{ "baz": 1234, ... } // OK
{ ... } // NOT OK
{ "baz": 1234, "buzz": 1234, ... } // NOT OK
I could do a oneOf
but that doesn't allow foo
to be present with the others, anyOf
allows for baz
,buzz
, and fizz
to be present with each other which is not possible.
I tried to define something like the following:
{
"type": "object",
"properties": {
"foo": {"type": "string"},
"baz": {"type": "number"},
"buzz": {"type": "number"},
"fizz": {"type": "number"}
},
"anyOf": [
{"required": ["foo"]},
{"required": [{"oneOf": [
{"required": ["baz"]},
{"required": ["buzz"]},
{"required": ["fizz"]}
]}
]}
]
}
and
{
"type": "object",
"properties": {
"foo": {"type": "string"},
"baz": {"type": "number"},
"buzz": {"type": "number"},
"fizz": {"type": "number"}
},
"anyOf": [
{"required": ["foo"]},
{"oneOf": [
{"required": ["baz"]},
{"required": ["buzz"]},
{"required": ["fizz"]}
]
}
]
}
But that does not work and I just don't know enough about json schema yet to know if this possible.
You can make properties mutually exclusive in JSON Schema using pairwise exclusions, but this leads to combinatorial explosion. That becomes a problem when you have many mutually exclusive properties.
A linear solution is of the form:
This only pays off if you have many properties.
{ "oneOf": [
{ "required": ["baz"] },
{ "required": ["buzz"] },
{ "required": ["fizz"] },
{ "not":
{ "anyOf": [
{ "required": ["baz"] },
{ "required": ["buzz"] },
{ "required": ["fizz"] }
] }
}
] }
Combine this with @cloudfeet's answer to get the answer to your specific question.