Multiple Types

So far we have only described how to specify types uniquely. But we could also specify that a certain document may be any number of types, such as string or integer, object or array, etc.

The basic declaration of multiple types is through the "type" keyword, where we can now have an array containing different types. For example, the following schema specifies integers and strings:

{
    "type": ["integer", "string"]
}

In addition, we also have the empty schema, that specifies all possible types of JSON documents

{}

How restrictions work under multiple types

The Keyword restrictions work a little different when multiple (or no) types are defined. Recall how, in the schema:

{
    "type": "string",
    "minLength": 4
}

the keyword "minLength": 4 imposes the restriction that all documents specified by this schema must have length at least 4 (all documents specified are strings). Likewise, in the schema

{
    "type": "integer",
    "minimum": 2
}

the keyword "minimum": 2 imposes the restriction that all documents specified by it must be greater than or equal to 2 (all documents specified by the schema are integers).

In schemas that specify either integer or strings these restrictions work in a slightly different way. Restrictions are only checked when the document is of a type that is compatible with the keyword.

Consider for example the schema:

{
    "type": ["integer","string"],
    "minimum": 2,
    "minLength": 4
}

This schema specifies both integers that are greater than or equal than 2 and strings that are of length at least 4. In other words, the schema above is equivalent to:

{
    "anyOf": [
        {
            "type": "integer",
            "minimum": 2
        }, 
        {
            "type": "string",
            "minLength": 4
        }
    ]
}

In general, when multiple (or no) types are defined in the schema, the rule for restrictions is as follows: each keyword restriction only applies when validating documents that are of the type that is compatible with the keyword.

As another example, the following schema specifies JSON documents that are either arrays, strings, integers, numbers, boolean or nulls, and also objects that have the property "I_apply_only_to_objects":

{
    "required": ["I_apply_only_to_objects"]
}

This is again equivalent to

{
    "anyOf": [
        {
        "not": {
        "type": "object"
        }
         }, 
        {
            "type": "object",
            "required": ["I_apply_only_to_objects"] 
        }
    ]
}

A list of all keywords and the types compatible are given below:

type compatible keywords
string "type", "minLength", "maxLength", "pattern".
number "type", "minimum", "maximum", "exclusiveMinimum", "exclusiveMaximum", "multipleOf".
integer "type", "minimum", "maximum", "exclusiveMinimum", "exclusiveMaximum", "multipleOf".
boolean "type".
null "type".
array "type", "minItems", "maxItems", "items", "uniqueItems".
object "type", "properties", "additionalProperties", "required", "minProperties", "maxProperties", "dependencies", "patternProperties", "regexp".

Formal Specification

Multiple types are created according to the following grammar (most of the tokens here were defined in previous sections)

multSch :=   multRes (, multRes)*
multRes := type | strRes | numRes | arrRes | objRes
type := "type" : [typename (, typename)*]
typename := "string" | "integer" | "number" | "boolean" | "null" | "array" | "object"

Where as usual each of the words replaced for the multRes tokens is unique.

Formal Validation

We define the function Compatible(J,k) that takes a JSON document J and a key/value pair k of the form key: value and returns true if key is a string in the following list:

list of keywords
"type", "minLength", "maxLength", "pattern", "minimum", "maximum", "exclusiveMinimum", "exclusiveMaximum", "multipleOf", "minItems", "maxItems", "items", "uniqueItems", "properties", "additionalProperties", "required", "minProperties", "maxProperties", "dependencies", "patternProperties", "regexp".

and key is compatible to the type of J according to the compatibility table above. Otherwise, Compatible(J,k) returns false.

Let M be a multiple type Schema and J a JSON document. We say that J validates against M if one of the following holds:

Conclusions

Finally we must mention that the use of the type keyword is a highly recommended practice by the community. As we learnt in this section the multiple type instances can be easily simulated using boolean combinations of schemas and do not seem to expand the expressive power of JSON Schemas.