Reputation: 1284
I am using AJV
trying to validate some data and dynamically require properties based on another property's value.
What I am trying to validate is:
- enabled
is always required,
- if enabled
= true
then only one of the other properties (realtime
, threshold
or digest
) must be provided,
Sample payloads and expected results:
Should pass
{
"notifications": {
"enabled": false
}
}
Should pass
{
"notifications": {
"enabled": true,
"realtime": true
}
}
Should pass
{
"notifications": {
"enabled": true,
"digest": true
}
}
Should pass
{
"notifications": {
"enabled": true,
"threshold": {}
}
}
Should fail because enabled
= true
but no other property is set.
{
"notifications": {
"enabled": true
}
}
Should fail because enabled
= true
and more than one other property is set.
{
"notifications": {
"enabled": true,
"threshold": {},
"digest: true
}
}
Here's the validation schema I am using:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Settings",
"type": "object",
"properties": {
"notifications": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"realtime": {
"type": "boolean"
},
"threshold": {
"type": "object",
"properties": {
"detections": {
"type": "number"
},
"elapsed": {
"type": "number"
}
},
"required": ["detections", "elapsed"]
},
"digest": {
"type": "boolean"
}
},
"required": ["enabled"],
"if": {
"properties": { "enabled": true }
},
"then": {
"oneOf": [
{ "required": [ "realtime" ] },
{ "required": [ "threshold" ] },
{ "required": [ "digest" ] }
]
}
}
}
}
Thank you!
Upvotes: 3
Views: 3104
Reputation: 1284
Turns out I was very close and the problem was how the if
statement was being evaluated for true
. Here's the correct schema that validates (passes and fails) all examples above as expected:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Settings",
"type": "object",
"properties": {
"notifications": {
"type": "object",
"properties": {
"enabled": {
"type": "boolean"
},
"realtime": {
"type": "boolean"
},
"threshold": {
"type": "object",
"properties": {
"detections": {
"type": "number"
},
"elapsed": {
"type": "number"
}
},
"required": ["detections", "elapsed"]
},
"digest": {
"type": "boolean"
}
},
"required": ["enabled"],
"if": {
"enabled": {
"const": true
}
},
"then": {
"oneOf": [
{
"required": ["realtime"]
},
{
"required": ["threshold"]
},
{
"required": ["digest"]
}
]
}
}
}
}
This part did the trick:
"if": {
"properties": {
"enabled": {
"const": true
}
}
}
Upvotes: 4