Reputation: 1207
I have a case where i am validating the required properties conditionally.
"not required" is not working as expected.
If 'profile' as profile1 then 'rate', 'trick' and 'tag' fields are required and 'code', 'name' and 'type' should not be present.
If 'profile' as profile2 then 'code' is required, and 'rate', 'tag', and 'trick' are not required.
if 'profile' is profile3 then 'rate', 'tag', 'trick', 'code', 'name' and 'type' are not required.
I am using schema draft version 4
{
"type": "object",
"properties": {
"id": { "type": "integer" },
"url": { "type": "string" },
"profile": { "type": "string" },
"rate": { "type": "string" },
"trick": { "type": "boolean" },
"tag": { "type": "string" },
"type": { "type": "string" },
"name": { "type": "string" },
"code": { "type": "string" }
},
"additionalProperties": false,
"required": [ "url", "profile" ],
"oneOf": [
{
"properties": { "profile": { "enum": [ "profile1" ] } },
"not": { "required": ["type", "name", "code"] }
},
{
"properties": { "profile": { "enum": [ "profile2" ] } },
"allOf": [
{ "required": [ "code" ] },
{ "not": { "required": ["rate", "tag", "trick"] } }
]
},
{
"properties": { "profile": { "enum": ["profile3"] } },
"not": { "required": ["rate", "trick", "tag", "type", "name", "code"] }
}
]
}
{
"id": 1,
"url": "url",
"profile": "profile2",
"type": "",
"name": "",
"code": ""
}
{
"id": 1,
"url": "url",
"profile": "profile3"
}
{
"id": 1,
"url": "url",
"profile": "profile1",
"rate": "",
"trick": false,
"tag": ""
}
{
"url": "url",
"profile": "profile3",
"code": ""
}
Upvotes: 2
Views: 1211
Reputation: 1980
I do not know whether this is a bug in json schema itself or the language server. somehow not required only seems to work with the first item in the array. This worked for me:
....
"allOf": [
{"not": {"required": ["type"]}},
{"not": {"required": ["name"]}},
{"not": {"required": ["code"]}}
]
....
Upvotes: 1
Reputation: 12335
I can see how you arrived at this approach, and you could make it work, but it's not the best approach.
The not
keyword inverts the assertion result of the value subschema.
If you take anyOf[2].not
schema...
{ "required": ["rate", "trick", "tag", "type", "name", "code"] }
This means, as I'm sure you know, all of those properties are required.
not
then inverts the result of applying that subschema.
Because in your object example which you expect to fail validation, it only has code
out of that array, then it doesn't meet the required
constraint.
You could make it not > anyOf > [required > rate, required > trick...
etc having many subschemas, but that would be a little ugly.
In stead, you could use an alternative approach, and specify what is ALLOWED...
Your anyOf
would then look like this (demo: https://jsonschema.dev/s/zG9GF):
"anyOf": [
false,
false,
{
"properties": {
"profile": {
"const": "profile3",
"id": true
}
},
"additionalProperties": false
}
]
You may find it more idiomatic to use if/then/else
keywords from draft-07, and then you can use allOf
and set the else
value to false
if you don't want to have a top level enum for profile
.
Upvotes: 1