I’m relatively new to JSON Schema and I’m struggling to create a schema that enforces a specific constraint on an array field. The requirement is that the array field, named "selection", can contain values "a", "b", "c", or "none". However, the array cannot contain both "none" and any of the values "a", "b", or "c" simultaneously. Here’s an example to clarify:
Valid JSONs:
{
"selection": ["a", "b", "c"]
}
{
"selection": ["none"]
}
Invalid JSON:
{
"selection": ["a", "b", "none"]
}
I’ve tried using oneOf
with const
and enum
, but I couldn’t get it to work as expected. Can someone assist me in creating a JSON Schema that properly enforces this constraint?
Here’s the schema I’ve been working with:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"selection": {
"type": "array",
"items": {
"oneOf": [
{
"const": "none"
},
{
"type": "string",
"enum": ["a", "b", "c"]
}
]
}
}
},
"required": ["selection"]
}
Any suggestions or corrections to this schema would be greatly appreciated. Thank you!
2
Answers
I got it working like this, but it requires draft2020-12 to support prefixItems if you want to support just a single entry of
none
in the array.You need
unevaluatedItems
which, when set tofalse
allows the presence ofnone
in the firstoneOf
schema that contains the enum causes it to not match.If you want
none
to be the only entry in the array when it exists, you’ll also needprefixItems
. Although you could probably get away withmaxItems:1
as well.It depends on how strict you want to be with your required format:
Vitest stackblitz
If you want to use draft-04 – draft-2019-09, you can use this syntax:
OR
The error messages are quite similar so either will work.
Versions of JSON Schema prior to 2020-12 allowed the use of
items: []
to indicate a tuple-like ordered index of values.The first example shows this pattern and uses
additionalItems: false
to prevent any other items to be added to the array.valid
{"selection": ["none"]}
{"selection": ["a","a","a"]}
{"selection": ["a"]}
{"selection": ["a","b"]}
invalid
{"selection": ["a","a","none"]}
{"selection": ["none", "none"]}
The second example uses
maxItems
anditems: {}
(object) where the index value can only beconst: "none"
andmaxItems: 1
prevents any further indices to be populated.