jsonSchema attribute conditionally required
Depending on your situation, there are a few different approaches. I can think of four different ways to conditionally require a field.
Dependencies
The dependencies
keyword is a conditional variation of the required
keyword. Foreach property in dependencies
, if the property is present in the JSON being validated, then the schema associated with that key must also be valid. If the "foo" property is present, then the "bar" property is required
{
"type": "object",
"properties": {
"foo": { "type": "string" },
"bar": { "type": "string" }
},
"dependencies": {
"foo": { "required": ["bar"] }
}
}
There is also a short form if the schema only contains the required
keyword.
{
"type": "object",
"properties": {
"foo": { "type": "string" },
"bar": { "type": "string" }
},
"dependencies": {
"foo": ["bar"]
}
}
Implication
If your condition depends on the value of a field, you can use a boolean logic concept called implication. "A implies B" effectively means, if A is true then B must also be true. Implication can also be expressed as "!A or B". Either the "foo" property does not equal "bar", or the "bar" property is required. Or, in other words: If the "foo" property equals "bar", Then the "bar" property is required
{
"type": "object",
"properties": {
"foo": { "type": "string" },
"bar": { "type": "string" }
},
"anyOf": [
{
"not": {
"properties": {
"foo": { "const": "bar" }
},
"required": ["foo"]
}
},
{ "required": ["bar"] }
]
}
If "foo" is not equal to "bar", #/anyOf/0
matches and validation succeeds. If "foo" equals "bar", #/anyOf/0
fails and #/anyOf/1
must be valid for the anyOf
validation to be successful.
Enum
If your conditional is based on an enum, it's a little more straight forward. "foo" can be "bar" or "baz". If "foo" equals "bar", then "bar" is required. If "foo" equals "baz", then "baz" is required.
{
"type": "object",
"properties": {
"foo": { "enum": ["bar", "baz"] },
"bar": { "type": "string" },
"baz": { "type": "string" }
},
"anyOf": [
{
"properties": {
"foo": { "const": "bar" }
},
"required": ["bar"]
},
{
"properties": {
"foo": { "const": "baz" }
},
"required": ["baz"]
}
]
}
If-Then-Else
A relatively new addition to JSON Schema (draft-07) adds the if
, then
and else
keywords. If the "foo" property equals "bar", Then the "bar" property is required
{
"type": "object",
"properties": {
"foo": { "type": "string" },
"bar": { "type": "string" }
},
"if": {
"properties": {
"foo": { "const": "bar" }
},
"required": ["foo"]
},
"then": { "required": ["bar"] }
}
EDIT 12/23/2017: Implication section updated and If-Then-Else section added.
EDIT 06/04/2018: Bugfix for If-Then-Else and update singleton enum
s to use const
.
tom redfern
I spend the time between weekends programming programmers. Want to get in touch? tom.redfern ((at)) Google's popular electronic mail service or https://www.linkedin.com/in/tomredfern/
Updated on June 17, 2021Comments
-
tom redfern almost 3 years
In jsonSchema you can indicate whether defined fields are mandatory or not using the "required" attribute:
{ "$schema": "http://json-schema.org/draft-04/schema#", "type": "object", "properties": { "header": { "type": "object", "properties": { "messageName": { "type": "string" }, "messageVersion": { "type": "string" } }, "required": [ "messageName", "messageVersion" ] } }, "required": [ "header" ] }
In certain cases, I would like the messageVersion field not to be mandatory. Is there any way to make the mandatory-ness of the this field conditional?
-
scubbo about 6 yearsThis is a wonderful reference, thank you! Out of interest, why did you use a single-value enum rather than a const in the third example? Also, do you have any stylistic advice for having multiple
if-then-else
in the same schema? At the moment I have anallOf
at the top-level, which contains oneallOf
per conditional, but it feels like I'm missing something... -
Jason Desrosiers about 6 years@scubbo I wrote this before the
const
keyword existed (it was added draft-06). Maybe next time I feel like this question needs an update, I'll change those toconst
. -
Jason Desrosiers about 6 years@scubbo I'm not a fan of the
if-then-else
keywords and I refuse to use them. But, if you choose to use it, I suggest always wrapping them in anallOf
that contains only those three keywords.{ ...other_keywords..., "allOf": [{ "if": ..., "then": ..., "else": ... }], ...more_keywords... }
-
user4581301 almost 6 years@Jason Why not a fan of
if...
? I think a brief opinion on this in your answer would be entirely justified. Or is it a long story? -
Jason Desrosiers almost 6 years@ClayBridges The comment section isn't the right place for that discussion, but here's the short version. As a general rule, JSON Schema keywords are stateless. No Information other than the keyword value can be used to validate the instance.
if
,then
, andelse
violate this rule because they depend on each other. -
Ron almost 6 years@JasonDesrosiers wonderful answer, thank you. But how about if a conditional required property depend on a parent object property? I raised another question here, hope you can help to resolve it. Thanks.
-
Raptor over 5 years"allOf" helped me add multiple if conditons!
-
Scott B about 5 yearsWould any of this work if you want to show/hide a form element based on value of a selected enum? I have a related unanswered question but this looks close. stackoverflow.com/questions/54653168/…
-
Jason Desrosiers about 5 years@ScottB I don't know. Form building is not part of the JSON Schema specification. You'll have to inquire about how to do it for the specific tool you are trying to use. There is no standard for form building.
-
GGirard about 5 years@JasonDesrosiers do you know about any official documentation about
Implications
, especially their usage you demonstrated in the second case and the third,Enum
, case? -
Jason Desrosiers about 5 years@GGirard, this is the best treatment of the use of these patterns in JSON Schema that I'm aware of. The boolean operations are officially documented but the rest is just math.
allOf
== AND,anyOf
== OR,oneOf
== XOR, andnot
== NOT. You can google "boolean algebra" for more resources on the math stuff (such as implication). -
Alexey Shrub about 5 years@jason-desrosiers do you post somewhere more detailed description about why you don't like if-then-else? As for me it's looks most readable.
-
Jason Desrosiers about 5 years@AlexeyShrub I've been wanting to write about this for a while, but have been distracted by other things. I am a fan of the idea of a conditional. It does make it easier for people to understand. My objection is to the way it was defined as three separate stateful keywords (see previous comment). Having keywords that violate the architectural properties that other keywords follow makes JSON Schema validators harder to implement and less efficient. If conditionals were defined in a different way that was stateless, then I would have no objection.
-
Flair almost 5 yearsI tried implementing that above in my own example where if a required key on the base level has a certain value, then another key on the base level is required to exist, but the four methods do not work. I am not sure why. Does it not work if the certain value is of type object?
-
Jason Desrosiers almost 5 years@Flair, it sounds like you need some help applying the patterns. I'm happy to help, but the comments aren't a good place for that. I suggest you either create a new SO question (@ me and I'll check it out personally), or head over the the JSON Schema slack and we can discuss it there. join.slack.com/t/json-schema/shared_invite/…
-
Flair almost 5 years@JasonDesrosiers stackoverflow.com/questions/56299562/…
-
JHH over 4 yearsGoogled for conditional json schema and was led here. Fantastic answer, covers all aspects with simple examples. Well done. 👍
-
S.A. over 3 yearsHow could I extend this to a case where several properties conditionally influence the "required" rule? For example assuming that initially nothing is required, how to implement the following: Having keys A, B, C, D ... if "A" is "foo", C is required, if "B" is "foo", D is required, and if both "A" and "B" are "foo", both C and D are required. else, nothing is required.
-
Jaume Mussons Abad over 3 yearsThis is what i call a great and clear answer to the question, thanks