Multiple If-Then-Else not validating for JSON Schema - json

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 ifs and one of these thens will be ignored by a JSON parser.
You can get around this problem by wrapping your ifs 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 ifs and thens in a way that makes the schema difficult to decipher.
{
"definitions": {},
"else": {},
"if": {},
"properties": {},
"then": {},
"type": "object",
}

Related

Json schema not validating as expected

I am working on a Json schema for validation but it does not seem to be working.
Apart from the if then condition, the rest works fine but even though i am following the example provided in jsonschema - Applying Subschemas Conditionally, it does not work.
This is the schema
'''
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"identifierKey": {
"type": "string",
"pattern": "^[a-z][a-z0-9]*(_[a-z0-9]+)*$",
"minLength": 2
},
"uuid": {
"type": "string",
"pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$",
"minLength": 36,
"maxLength": 36
},
"mail_identifierKey": {
"pattern": "^(?:(?!.*?[.]{2})[a-zA-Z0-9](?:[a-zA-Z0-9.+!%-]{1,64}|)|\"[a-zA-Z0-9.+!% -]{1,64}\")#[a-zA-Z0-9][a-zA-Z0-9.-]+(.[a-z]{2,}|.[0-9]{1,})$"
},
"question_type": {
"enum": [
"barcode",
"name",
"nps",
"single_choice",
"text",
"date",
"number",
"id",
"mail_address",
"multiple_choice",
"phone_number",
"zip_code",
"rating"
]
},
"question": {
"type": "object",
"additionalProperties": false,
"properties": {
"key": {
"$ref": "#/definitions/identifierKey"
},
"type": {
"$ref": "#/definitions/question_type"
}
},
"required": ["key", "type"]
},
"answers": {
"type":"array",
"items": {
"type": "object",
"properties": {
"question": {
"$ref": "#/definitions/question"
},
"status": {
"type": "string"
}
},
"allOf": [
{"if": {
"properties": { "question": { "const": "rating" } } },
"then": {
"properties": { "value": { "type": "number", "minimum": 1, "maximum": 5 } } }
},
{"if": {
"properties": { "question": { "const": "zip_code" } } },
"then": {
"properties": { "value": { "type": "string", "$ref": "#/definitions/identifierKey","minLength": 4, "maxLength": 10 } } }
},
{"if": {
"properties": { "question": { "const": "phone_number" } } },
"then": {
"properties": { "value": { "type": "string", "minLength": 8, "maxLength": 15 } } }
},
{"if": {
"properties": { "question": { "const": "multiple_choice" } } },
"then": {
"properties": { "value": { "type": "array", "minItems": 1, "uniqueItems": true,
"contains": { "type": "string" } }
}
}
},
{"if": {
"properties": { "question": { "const": "single_choice" } } },
"then": {
"properties": { "value": {"type": "string","$ref": "#/definitions/identifierKey"} } }
},
{"if": {
"properties": { "question": { "const": "mail_address" } } },
"then": {
"properties": { "value": {"type": "string","$ref": "#/definitions/mail_identifierKey"} } }
},
{"if": {
"properties": { "question": { "const": "id" } } },
"then": {
"properties": { "value": {"type": "string","$ref": "#/definitions/uuid"} } }
},
{"if": {
"properties": { "question": { "const": "number" } } },
"then": {
"properties": { "value": {"type": "number"} } }
},
{"if": {
"properties": { "question": { "const": "text" } } },
"then": {
"properties": { "value": {"type": "string"} } }
},
{"if": {
"properties": { "question": { "const": "date" } } },
"then": {
"properties": { "value": {"type": "string", "format": "date"} } }
},
{"if": {
"properties": { "question": { "const": "nps" } } },
"then": {
"properties": { "value": {"type": "number", "minimum": 1, "maximum":10 } } }
},
{"if": {
"properties": { "question": { "const": "name" } } },
"then": {
"properties": { "value": {"type": "string" } } }
},
{"if": {
"properties": { "question": { "const": "barcode" } } },
"then": {
"properties": { "value": {"type": "number" } } }
}
]
}
}
},
"properties": {
"answers": {
"$ref": "#/definitions/answers"
}
}
}
'''
and this is what i am trying to validate
''' {
"$schema": "./blank.json",
"answers":[ {
"status": "hello1",
"question": {
"key": "hello",
"type": "rating"
},
"value": 1234
}]
} '''
i am following the example below but not able to figure out what i am missing
https://json-schema.org/understanding-json-schema/reference/conditionals.html
Okay... I see the problem.
Here's the if subschema that you expect to trigger for your data
{
"properties": {
"question": { "const": "rating" }
}
}
However, in your data, question has a type property.
"question": {
"key": "hello",
"type": "rating"
}
This means that the if subschema isn't passing because {"key": "hello", "type": "rating" } != "rating".
You'll need to update your if subschema to account for this property hierarchy.
{
"properties": {
"question": {
"properties": {
"type": { "const": "rating" }
}
}
}
}
You'll need to do this for all of the if subschemas.
Making just this change gives this error on my validator:
{
"valid": false,
"keywordLocation": "#/properties/answers/$ref/items/allOf/0/then/properties/value/maximum",
"absoluteKeywordLocation": "https://json-everything/base#/definitions/question_type/items/allOf/0/then/properties/value/maximum",
"instanceLocation": "#/answers/0/value",
"error": "1234 is greater than or equal to 5"
}

JSON Schema - Required object by value

it is possible to validate required values in a JSON Schema?
I have the following JSON:
{
"genericData": [
{
"name": "field_one",
"value": "data_one"
},
{
"name": "field_two",
"value": [
"array_data_one",
"array_data_two"
]
},
{
"name": "field_three",
"value": {
"attr_one": "some_data",
"attr_two": "more_data"
}
}
]
}
For validating the objects in the array i have the following JSON Schema:
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"genericData": {
"type":"array",
"minItems": 2,
"items": [
{
"type": "object",
"if": {
"properties": {
"name": {
"enum": [
"field_one"
]
}
}
},
"then": {
"properties": {
"name": {
"type": "string"
},
"value": {
"type": "string"
}
}
}
},
{
"type": "object",
"if": {
"properties": {
"name": {
"enum": [
"field_two"
]
}
}
},
"then": {
"properties": {
"name": {
"type": "string"
},
"value": {
"type": "array",
"minItems": 1,
"items": [
{
"type": "string"
}
]
}
}
}
},
{
"type": "object",
"if": {
"properties": {
"name": {
"enum": [
"field_three"
]
}
}
},
"then": {
"properties": {
"name": {
"type": "string"
},
"value": {
"type": "object",
"properties": {
"attr_one": {
"type": "string"
},
"attr_two": {
"type": "string"
}
},
"required": [
"attr_one",
"attr_two"
]
}
}
}
}
]
}
}
}
Now my question is: Is it possible to set the objects e.g. with the names "field_one" and "field_two" as required? I tried to set the propertie "name", in the "then" clause as required, but this has no impact!
Thanks,
Andreas
I found the solution. The keywords "allOf" and "contains" in combination with "pattern" did what i want:
...
"genericData": {
"type":"array",
"minItems": 2,
"allOf": [
{
"contains": {
"type": "object",
"properties": {
"name": {
"type": "string",
"pattern": "^field_one$"
}
}
}
},
{
"contains": {
"type": "object",
"properties": {
"name": {
"type": "string",
"pattern": "^field_two$"
}
}
}
}
],
"items": [
{
"type": "object",
"if": {
"properties": {
"name": {
"enum": [
"field_one"
]
}
}
},
...

Validating nested JSON attribute in schema

Here is my JSON schema and JSON as shown below at the bottom and using ajv validator to support json spec draft 7.
By default, the 'science' object must be represented as:
//Default science object
{"type": "science", "rule": {"sciencePattern": {}}}
where the 'rule' and 'sciencePattern' MUST be there.
However, if the 'sciencePattern' about to contains other attributes (as per the schema), then the below validation should kick in:
If the default science object is present, then the "scored" attributes in "arts" object should be REQUIRED.
If the NESTED "scored" array attribute is present within rule as:
{ "type": "science", "rule":{"sciencePattern":{"marks":{"scored":[10]}}} }
then the "scored" attributes in "arts" object should not be REQUIRED. In other words, if some one specify "scored" attribute withn the "arts" object, the schema validation should complain as there is a "scored" attribute is available in "science" object.
//JSON Schema
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"exam"
],
"properties": {
"exam": {
"type": "array",
"minItems": 1,
"items": {
"anyOf": [
{
"$ref": "#/definitions/science"
},
{
"$ref": "#/definitions/arts"
}
]
}
},
"if": {
"type": "object",
"required": [
"type",
"rule"
],
"properties": {
"type": {
"const": "science"
},
"rule": {
"type": "object",
"required": [
"sciencePattern"
],
"properties": {
"sciencePattern": {
"$ref": "#/definitions/sciencePattern"
}
}
}
}
},
"then": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"const": "arts"
},
"not": {
"required": [
"scored"
]
}
}
}
},
"definitions": {
"sciencePattern": {
"type": "object",
"required": [
"marks"
],
"properties": {
"marks": {
"type": "object",
"required": [
"scored"
],
"properties": {
"scored": {
"type": "array"
}
}
}
}
},
"science": {
"type": "object",
"properties": {
"type": {
"const": "science"
},
"rule": {
"required": [
"sciencePattern"
],
"properties": {
"sciencePattern": {
"$ref": "#/definitions/sciencePattern"
}
}
}
}
},
"arts": {
"required": [
"scored"
],
"properties": {
"type": {
"const": "arts"
},
"scored": {
"type": "number"
},
"remarks": {
"type": "string"
}
}
}
}
}
and My JSON
{
"exam": [
{
"type": "science",
"rule": {
"sciencePattern": {
"marks": {
"scored": [10]
}
}
}
},
{
"type": "arts",
"scored": 10 //This should complain as 'scored' is available above in science
}
]
}
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"required": [
"exam"
],
"properties": {
"exam": {
"type": "array",
"allOf":[
{
"if": {
"contains": {
"type": "object",
"required": [
"type"
],
"properties": {
"type": {
"const": "science"
}
}
}
},
"then":{
"required":["rule", "sciencePattern"]
}
},
{
"if": {
"contains": {
"type": "object",
"required":["type","rule", "sciencePattern"],
"properties": {
"type": {
"const": "science"
}
}
}
},
"then":{
"required":["scored"]
}
},
{
"if": {
"contains": {
"type": "object",
"required": [
"type",
"rule"
],
"properties": {
"type": {
"const": "science"
},
"rule": {
"type": "object",
"required": [
"sciencePattern"
],
"properties": {
"sciencePattern": {
"$ref": "#/definitions/emptySciencePattern"
}
}
}
}
}
},
"then": {
"contains": {
"type": "object",
"required": ["type", "scored"],
"properties": {
"type": {
"const": "arts"
}
}
}
},
"else": {
"if": {
"contains": {
"type": "object",
"required": [
"type",
"rule"
],
"properties": {
"type": {
"const": "science"
},
"rule": {
"type": "object",
"required": [
"sciencePattern"
],
"properties": {
"sciencePattern": {
"$ref": "#/definitions/sciencePattern"
}
}
}
}
}
},
"then": {
"contains": {
"required": [
"type"
],
"properties": {
"type": {
"const": "arts"
}
},
"not": {
"required": ["scored"]
}
}
}
}
}],
"minItems": 1,
"items": {
"anyOf": [{
"$ref": "#/definitions/science"
}, {
"$ref": "#/definitions/arts"
}]
}
}
},
"definitions": {
"rule": {
"type": "object",
"required": ["sciencePattern"],
"properties": {
"sciencePattern": {
"$ref": "#/definitions/sciencePattern"
}
}
},
"emptySciencePattern": {
"type": "object",
"maxProperties": 0,
"additionalProperties": false,
"properties": {}
},
"sciencePattern": {
"type": "object",
"properties": {
"marks": {
"type": "object",
"properties": {
"scored": {
"type": "array"
}
}
}
}
},
"science": {
"type": "object",
"required": ["rule"],
"properties": {
"type": {
"const": "science"
},
"rule": {
"$ref":"#/definitions/rule"
}
}
},
"arts": {
"properties": {
"type": {
"const": "arts"
},
"scored": {
"type": "number"
},
"remarks": {
"type": "string"
}
}
}
}
}

JSON Schema not validating required attributes

Here is the criteria: the individual region object can co-exist withing the array along with ONLY asia/europe/austrlia (either one region at a time from asia/europe/austrlia).
In addition to this every region object can have few required attributes and nested one.
The issue is the schema validator is not complaining about the required attribute (i.e. width attribute from dimension object)
Here is the JSON Schema
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"stat_data": {
"type": "array",
"if": {
"contains": {
"type": "object",
"properties": {
"region": {
"type": "string",
"enum": [
"europe"
]
}
}
}
},
"then": {
"not": {
"contains": {
"type": "object",
"properties": {
"region": {
"type": "string",
"enum": [
"asia",
"australia"
]
}
}
}
}
},
"else": {
"if": {
"contains": {
"type": "object",
"properties": {
"region": {
"type": "string",
"enum": [
"asia"
]
}
}
}
},
"then": {
"not": {
"contains": {
"type": "object",
"properties": {
"region": {
"type": "string",
"enum": [
"europe",
"australia"
]
}
}
}
}
},
"else": {
"if": {
"contains": {
"type": "object",
"properties": {
"region": {
"type": "string",
"enum": [
"australia"
]
}
}
}
},
"then": {
"not": {
"contains": {
"type": "object",
"properties": {
"region": {
"type": "string",
"enum": [
"europe",
"asia"
]
}
}
}
}
},
"else": {}
}
},
"items": {
"type": "object",
"properties": {
"details": {
"$ref": "#/definitions/dimension"
},
"population": {
"$ref": "#/definitions/details"
},
"dimension": {
"$ref": "#/definitions/population"
},
"region": {
"enum": [
"asia",
"europe",
"australia",
"some-pencil-region",
"some-oil-pastels-region"
]
}
}
}
}
},
"definitions": {
"dimension": {
"type": "object",
"required": [
"width"
],
"properties": {
"height": {
"type": "integer"
},
"width": {
"type": "integer"
}
}
},
"details": {
"type": "object",
"properties": {
"brand": {
"type": "string"
},
"year": {
"type": "integer"
}
}
},
"population": {
"type": "object",
"properties": {
"change": {
"type": "integer"
},
"year": {
"type": "integer"
}
}
}
}
}
and the JSON
{
"stat_data": [
{
"region": "some-pencil-region",
"details": {
"brand": "Camlin",
"year": 2019
}
},
{
"region": "some-oil-pastels-region",
"height": 30
},
{
"region": "asia",
"population": {
"year": 2018,
"change": 2
}
}
]
}
You can check at _https://jsonschema.dev/ by copying schema and json in the editor
Maybe your JSON validator doesn't catch the issue? JSONBuddy shows a message about a missing "width" property:

How to simplify multiple JSON-Schema switch-like statements

There is an example of a switch-like condition in the JSON Schema documentation.
https://json-schema.org/understanding-json-schema/reference/conditionals.html
I have added two more countries to the example, which both should have the same postal code patterns as Netherlands. I can get this example to work with two additional if/then structures, but it becomes messy when more items are to be added.
Is there DRYer version, e.g. like the hypothetical one below?
"properties": { "country": { "const": ["Netherlands", "Upperlands", "Lowerlands" } }
{
"type": "object",
"properties": {
"street_address": {
"type": "string"
},
"country": {
"enum": ["United States of America", "Canada", "Netherlands",
"Upperlands","Lowerlands"]
}
},
"allOf": [
{
"if": {
"properties": { "country": { "const": "United States of America" } }
},
"then": {
"properties": { "postal_code": { "pattern": "[0-9]{5}(-[0-9]{4})?" } }
}
},
{
"if": {
"properties": { "country": { "const": "Canada" } }
},
"then": {
"properties": { "postal_code": { "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" } }
}
},
{
"if": {
"properties": { "country": { "const": "Netherlands" } }
},
"then": {
"properties": { "postal_code": { "pattern": "[0-9]{4} [A-Z]{2}" } }
}
}
]
}
You could use the enum pattern instead. It's less verbose and easier to read, but the error messages you get are terrible, so I suggest you stick with the if/then pattern. Here's what using the enum pattern would look like.
{
"type": "object",
"properties": {
"street_address": {
"type": "string"
},
"country": {
"enum": ["United States of America", "Canada", "Netherlands",
"Upperlands","Lowerlands"]
}
},
"anyOf": [
{
"properties": {
"country": { "const": "United States of America" },
"postal_code": { "pattern": "[0-9]{5}(-[0-9]{4})?" }
}
},
{
"properties": {
"country": { "const": "Canada" },
"postal_code": { "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" }
}
},
{
"properties": {
"country": { "const": "Netherlands" },
"postal_code": { "pattern": "[0-9]{4} [A-Z]{2}" }
}
}
]
}
Although there isn't good way around the verbosity, there is something you can do to improve readability/maintainability. You can use definitions to hide the verbose parts.
{
"type": "object",
"properties": {
"street_address": {
"type": "string"
},
"country": {
"enum": ["United States of America", "Canada", "Netherlands",
"Upperlands","Lowerlands"]
}
},
"allOf": [
{ "$ref": "#/definitions/validate-us-postal-code" },
{ "$ref": "#/definitions/validate-ca-postal-code" },
{ "$ref": "#/definitions/validate-nl-postal-code" }
]
"definitions": {
"validate-us-postal-code": {
"if": {
"properties": { "country": { "const": "United States of America" } }
},
"then": {
"properties": { "postal_code": { "pattern": "[0-9]{5}(-[0-9]{4})?" } }
}
},
"validate-ca-postal-code": {
"if": {
"properties": { "country": { "const": "Canada" } }
},
"then": {
"properties": { "postal_code": { "pattern": "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]" } }
}
},
"validate-nl-postal-code": {
"if": {
"properties": { "country": { "const": "Netherlands" } }
},
"then": {
"properties": { "postal_code": { "pattern": "[0-9]{4} [A-Z]{2}" } }
}
}
}
}
This allows someone to be able to understand everything this schema does just by reading the first few lines. The verbose/complicated stuff is pushed to the bottom where you don't have to deal with it if you don't need to.