Schema Composition

JSON Schema includes a few keywords for combining schemas together. Note that this doesn't necessarily mean combining schemas from multiple files or JSON trees, though these facilities help to enable that and are described in Structuring a complex schema. Combining schemas may be as simple as allowing a value to be validated against multiple criteria at the same time.

These keywords correspond to well known boolean algebra concepts like AND, OR, XOR, and NOT. You can often use these keywords to express complex constraints that can't otherwise be expressed with standard JSON Schema keywords.

The keywords used to combine schemas are:

  • allOf: (AND) Must be valid against all of the subschemas
  • anyOf: (OR) Must be valid against any of the subschemas
  • oneOf: (XOR) Must be valid against exactly one of the subschemas

All of these keywords must be set to an array, where each item is a schema.

In addition, there is:

  • not: (NOT) Must not be valid against the given schema

allOf

To validate against allOf, the given data must be valid against all of the given subschemas.

schema
1
{
2
"allOf": [
3
{ "type": "string" },
4
{ "maxLength": 5 }
5
]
6
}

A snippet of the British royal family tree

data
1
"short"
compliant to schema
data
1
"too long"
not compliant to schema

allOf can not be used to "extend" a schema to add more details to it in the sense of object-oriented inheritance. Instances must independently be valid against "all of" the schemas in the allOf. See the section on Extending Closed Schemas for more information.

anyOf

To validate against anyOf, the given data must be valid against any (one or more) of the given subschemas.

schema
1
{
2
"anyOf": [
3
{ "type": "string", "maxLength": 5 },
4
{ "type": "number", "minimum": 0 }
5
]
6
}

A snippet of the British royal family tree

data
1
"short"
compliant to schema
data
1
"too long"
not compliant to schema
data
1
12"
compliant to schema
data
1
-5
not compliant to schema

oneOf

To validate against oneOf, the given data must be valid against exactly one of the given subschemas.

schema
1
{
2
"oneOf": [
3
{ "type": "number", "multipleOf": 5 },
4
{ "type": "number", "multipleOf": 3 }
5
]
6
}
data
1
10
compliant to schema
data
1
9
compliant to schema

Not a multiple of either 5 or 3.

data
1
2
not compliant to schema

Multiple of both 5 and 3 is rejected.

data
1
15
not compliant to schema

not

The not keyword declares that an instance validates if it doesn't validate against the given subschema.

For example, the following schema validates against anything that is not a string:

schema
1
{ "not": { "type": "string" } }
data
1
42
compliant to schema
data
1
{ "key": "value" }
compliant to schema
data
1
"I am a string"
not compliant to schema

Properties of Schema Composition

Illogical Schemas

Note that it's quite easy to create schemas that are logical impossibilities with these keywords. The following example creates a schema that won't validate against anything (since something may not be both a string and a number at the same time):

schema
1
{
2
"allOf": [
3
{ "type": "string" },
4
{ "type": "number" }
5
]
6
}
data
1
"No way"
not compliant to schema
data
1
-1
not compliant to schema

Factoring Schemas

Note that it's possible to "factor" out the common parts of the subschemas. The following two schemas are equivalent.

schema
1
{
2
"oneOf": [
3
{ "type": "number", "multipleOf": 5 },
4
{ "type": "number", "multipleOf": 3 }
5
]
6
}
schema
1
{
2
"type": "number",
3
"oneOf": [
4
{ "multipleOf": 5 },
5
{ "multipleOf": 3 }
6
]
7
}