I have a program that I have built that takes a JSON object and produces a JSON schema file based on the details of the input. When I use this program to generate a schema for a smaller JSON object, the schema works correctly and validates as expected. In this smaller schema there is only one if-then-else block.
However when I attempt to generate a schema that makes use of several if-then-else blocks the if-then-else validation seems to stop working at all and will allow anything through.
I'll post an example below to be more clear.
JSON Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"question6-99": {
"type": "object",
"properties": {
"answer": {
"type": "string",
"enum": ["Yes", "No"]
}
}
},
"question6-100": {
"type": "object",
"properties": {
"answer": {
"type": "string",
"enum": ["Mr","Ms","Mrs","Miss","Dr","Rev","Sir","Lady","Lord","Prof", ""]
}
}
}
},
"type": "object",
"properties": {
"form_submission": {
"type": "object",
"properties": {
"sections": {
"type": "object",
"properties": {
"6": {
"type": "object",
"properties": {
"questions": {
"type": "object",
"properties": {
"99": {
"$ref": "#/definitions/question6-99"
},
"100": {
"$ref": "#/definitions/question6-100"
}
},
"if": {
"properties": {
"99": {
"properties": {
"answer": {
"enum": [
"Yes"
]
}
},
"required": [
"answer"
]
}
},
"required": [
"100"
]
},
"then": {
"properties": {
"100": {
"properties": {
"answer": {
"minLength": 1
}
}
}
}
},
"else": {
"properties": {
"100": {
"properties": {
"answer": {
"maxLength": 0
}
}
}
}
}
}
}
}
},
"required": [
"6"
]
}
}
}
}
}
JSON Object being validated
{
"form_submission": {
"sections": {
"1": {
"questions": {
"99": {
"answer": "Yes",
},
"100": {
"answer": "",
}
}
}
}
}
}
For the above example, if the schema is used to validate the object, the answer for question 100 must be answered when question 99 is answered "yes". This works correctly.
However if I then attempt to use the schema below, which uses two if-then-else blocks against the second JSON object, no if-then-else validation occurs.
I'm just wondering if I have done something wrong with the structure of my schema code that is stopping the validation from happening correctly.
Schema using two If-then-else
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"question6-99": {
"type": "object",
"properties": {
"answer": {
"type": "string",
"minLength": 1,
"enum": ["Yes", "No"]
}
}
},
"question6-100": {
"type": "object",
"properties": {
"answer": {
"type": "string",
"enum": ["Mr", "Ms", "Mrs", "Miss", "Dr", "Rev", "Sir", "Lady", "Lord", "Prof", ""]
}
}
},
"question6-101": {
"type": "object",
"properties": {
"answer": {
"type": "string"
}
}
}
},
"type": "object",
"properties": {
"form_submission": {
"type": "object",
"properties": {
"sections": {
"type": "object",
"properties": {
"6": {
"type": "object",
"properties": {
"questions": {
"type": "object",
"properties": {
"99": {
"$ref": "#/definitions/question6-99"
},
"100": {
"$ref": "#/definitions/question6-100"
},
"101": {
"$ref": "#/definitions/question6-101"
}
},
"required": ["99", "100", "101", "102", "103", "104", "105", "111"],
"if": {
"properties": {
"99": {
"properties": {
"answer": {
"enum": ["Yes"]
}
},
"required": ["answer"]
}
},
"required": ["100"]
},
"then": {
"properties": {
"100": {
"properties": {
"answer": {
"minLength": 1
}
}
}
}
},
"else": {
"properties": {
"100": {
"properties": {
"answer": {
"maxLength": 0
}
}
}
}
},
"if": {
"properties": {
"99": {
"properties": {
"answer": {
"enum": ["Yes"]
}
},
"required": ["answer"]
}
},
"required": ["101"]
},
"then": {
"properties": {
"101": {
"properties": {
"answer": {
"minLength": 1
}
}
}
}
},
"else": {
"properties": {
"101": {
"properties": {
"answer": {
"maxLength": 0
}
}
}
}
}
}
}
}
},
"required": ["1"]
}
}
}
}
}
Second schema to validate
{
"form_submission": {
"id": "80035",
"status": "Incomplete",
"validated": true,
"failure_reason": "",
"sections": {
"1": {
"questions": {
"99": {
"answer": "Yes",
"web_validated": true,
"web_error_string": "",
"server_error_string": ""
},
"100": {
"answer": "",
"web_validated": true,
"web_error_string": "",
"server_error_string": ""
},
"101": {
"answer": "Yes",
"web_validated": true,
"web_error_string": "",
"server_error_string": ""
}
},
"name": "",
"validated": true,
"server_validated": true,
"notes": ""
}
},
"submitted_section_id": 11
}
}
Added allOf to Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"question6-99": {
"type": "object",
"properties": {
"answer": {
"type": "string",
"minLength": 1,
"enum": ["Yes", "No"]
}
}
},
"question6-100": {
"type": "object",
"properties": {
"answer": {
"type": "string",
"enum": ["Mr", "Ms", "Mrs", "Miss", "Dr", "Rev", "Sir", "Lady", "Lord", "Prof", ""]
}
}
},
"question6-101": {
"type": "object",
"properties": {
"answer": {
"type": "string"
}
}
}
},
"type": "object",
"properties": {
"form_submission": {
"type": "object",
"properties": {
"sections": {
"type": "object",
"properties": {
"6": {
"type": "object",
"properties": {
"questions": {
"type": "object",
"properties": {
"99": {
"$ref": "#/definitions/question6-99"
},
"100": {
"$ref": "#/definitions/question6-100"
},
"101": {
"$ref": "#/definitions/question6-101"
}
},
"required": ["99", "100", "101", "102", "103", "104", "105", "111"],
"allOf": [
{
"if": {
"properties": {
"99": {
"properties": {
"answer": {
"enum": ["Yes"]
}
},
"required": ["answer"]
}
},
"required": ["100"]
},
"then": {
"properties": {
"100": {
"properties": {
"answer": {
"minLength": 1
}
}
}
}
},
"else": {
"properties": {
"100": {
"properties": {
"answer": {
"maxLength": 0
}
}
}
}
}},
{
"if": {
"properties": {
"99": {
"properties": {
"answer": {
"enum": ["Yes"]
}
},
"required": ["answer"]
}
},
"required": ["101"]
},
"then": {
"properties": {
"101": {
"properties": {
"answer": {
"minLength": 1
}
}
}
}
},
"else": {
"properties": {
"101": {
"properties": {
"answer": {
"maxLength": 0
}
}
}
}
}
}
]
}
}
}
},
"required": ["1"]
}
}
}
}
}
If we remove the complicated bits, I think the problem becomes clear.
{
"if": { ... },
"then": { ... },
"if": { ... },
"then": { ... }
}
In JSON the value of duplicated keys is undefined. One of these if
s and one of these then
s will be ignored by a JSON parser.
You can get around this problem by wrapping your if
s in an allOf
.
{
"allOf": [
{
"if": { ... },
"then": { ... }
},
{
"if": { ... },
"then": { ... }
}
]
}
It's good practice to always wrap your if
/then
/else
in allOf
even if you have only one. This is because a JSON object is by definition unordered. Therefore, some tool might rearrange your keywords splitting up the if
s and then
s in a way that makes the schema difficult to decipher.
{
"definitions": {},
"else": {},
"if": {},
"properties": {},
"then": {},
"type": "object",
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With