Basic Types
JSON Documents can be either basic values (strings, numbers, integers, the boolean constants or null), or ordered or unordered list of key:value pairs. We can use JSON Schema to specify that documents can be any of these. For now we concentrate on the specification for values. There are five basic value types supported by JSON Schema:
String Schemas
One of the most basic forms of values that appear in JSON documents are strings of text. In JSON schema we can specify that a document is a string by using the keyword string
as the value of the name type
. That is, the document
{"type": "string"}
is a JSON Schema that valiadates against any JSON that is a string. Note that a JSON document is a string only if it is a sequence of Unicode characters enclosed in double quotation marks. That is, "I am a string"
is a valid JSON document that satisfies the above schema, but so is the sequence "42"
, or "true"
. On the other hand
42
is a JSON document that will not satisfy the above schema, and neither will the document true
.
Restrictions
In order to control the length of our string we can use the keywords minLength
and maxLength
. To restrict the shape of the string even further we can specify that it conforms to a regular expression using the keyword pattern
.
Restricting the length of a string
We use the "minLength"
and "maxLength"
keywords to specify that the length of a string has to fall into a particular interval. For instance, the following schema
{
"type": "string",
"minLength": 3,
"maxLength": 7
}
specifies that our JSON document is a string whose minimum length is 3 and whose maximum length is 7. The keywords "minLength"
and "maxLength"
always have a non-negative integer as their value. The document "This is"
will validate against the above schema, as it is of length seven. On the other hand "Is"
, or "This is not valid"
will not validate against the schema, as the former is too short, while the latter is too long.
Regular expressions
To specify that a string conforms to a regular expression we use the keyword "pattern"
. For instance, if we want to enforce that the string is a valid email address with the extension gmail.com
that contains only letters of the alphabet, we could use the following JSON Schema.
{
"type": "string",
"pattern": "^[A-Za-z]*@gmail.com$"
}
Here we are specifying that the email address must end with @gmail.com
, while the part [A-Za-z]*
allows any string consisting of either lower or upper case characters. The symbols ^
and $
are used to signify that the matching of a regular expression is done against the entire string. Therefore, the document "adam@gmail.com"
validates against the schema above, but "g42s@gmail.com"
does not validate, as the first part before the @ contains a character that is not a letter.
For a more detailed introduction to regular expressions we refer the reader to check out the RegexOne website.
Formal Specification
String Schemas strSch are formally specified using the following grammar.
strSch := "type": "string" (, strRes)* strRes := minLen | maxLen | pattern minLen := "minLength": n maxLen := "maxLength": n pattern := "pattern": regExp
where each strRes token appears at most once in strSch, n is an arbitrary non-negative integer and r is a regular expression as specified in RegexOne website.
Formal Validation
Let S be a String Schema and J a JSON document. We say that J validates against S if for each key:value pair k in S one of the following holds:
- k is
"type":"string"
and J is a string - k is of the form
"minLength" : n
and J is a string of length at least n - k is of the form
"maxLength" : n
and J is a string of length at most n - k is of the form
"pattern" : "rexp"
and J is a string that matches the regular expression rexp
Note that in the formal definition we don not enforce the keyword type
to be specified. For instance the Schema
{
"minLength": 3,
"maxLength": 7
}
is well specified and will match any string whose length is between three and seven characters. This is a consequence of the fact that in the absence of explicit type definition we can still infer the base type by parsing other keywords. This behavior is specified in the multiple type
schemas section. We would, however, like to stress that explicitly specifying the type is a good practice that should always be adhered to.
Numeric Schemas
Another form of value in JSON are numbers. In JSON Schema we can
specify that a document must be a number by using the type
keyword. The document
{"type": "number"}
is a JSON Schema, and validates against any numeric value. For example, values 34
and 1.82
satisfy {"type": "number"}
, while "34"
does not, because it is a string.
If we need to specify that a value must be an integer, we use instead the keyword integer
:
{"type": "integer"}
Now the value 34
satisfies this schema, but 1.82
does not.
Restrictions
We can also specify additional constraints that the numbers must satisfy. All of these keywords can be use by either number
or integer
types.
Range
Suppose we need to specify a value for the age of a person, and we want it to be an integer between 0 and 150. We use the
"minimum"
and "maximum"
keywords:
{
"type": "integer",
"minimum": 0,
"maximum": 150
}
This document validates against any number between 0
and 150
.
By default the ranges are inclusive: "minimum": n
imposes the restriction that numbers need to be greater than or equal to n
, and "minimum": m
imposes that numbers need to be less than or equal to m
. This means that both 0
and 150
satisfy the schema above. We can switch the ranges to be exclusive by using the "exclusiveMinimum"
and "exclusiveMaximum"
keywords.
For example, the following schema validates against 0
, but not against 150
:
{
"type":"integer",
"minimum": 0,
"maximum": 150,
"exclusiveMaximum":true
}
If the "minimum": n
keyword is present together with the keyword "exclusiveMinimum":true
then the restriction imposes that numbers must be greater than n
, and if the "maximum": m
keyword is present together with "exclusiveMaximum":true
then the restriction is that the number must be lower than m
.
Multiplicity
We can also specify that a number must be the multiple of another number, as in the following schema:
{
"type": "integer",
"multipleOf": 10
}
This schema validates against any number that is a multiple of 10
.
Note that we can also use real numbers in "multipleOf"
, and we can combine it with range restrictions. For example, the schema
{
"type":"integer",
"multipleOf": 3.3,
"maximum": 7
}
validates against numbers 3.3
and 6.6
.
Formal Specification
Numeric schemas numSch are constructed using the following grammar:
numSch := "type": ("number" | "integer") (, numRes)* numRes := min | max | multiple min := "minimum": r (, exMin)? exMin := "exclusiveMinimum": bool max := "maximum": r (, exMax)? exMax := "exclusiveMaximum": bool multiple := "multipleOf": r (r≥0)
where each numSch can have at most one of each min, max and multiple. Here r is any positive decimal number, and bool is either true or false.
Validation
Let N be a numeric schema and J a JSON document. Then N validates against J if for each name/value pair k in N, one of the following holds:
- k is
"type":"number"
and J is a number. - k is
"type":"integer"
and J is an integer number (a number without the decimal.
marker). - k is
"multipleOf": r
for some positive decimal number r, and J is a number that is a multpiple of r. - k is
"minimum": r
for some decimal r, and J is a number that is strictly greater than r. - k is
"minimum": r
for some decimal r, J is a number that is equal to r and the pair"exclusiveMinimum": true
is not in N. - k is
"maximum": r
, for some decimal r, and J is a number that is stricly less than r. - k is
"maximum": r
for some decimal r, J is a number that is equal to r and the pair"exclusiveMinimum": true
is not in N.
Boolean Schemas
In order to specify a property that can be either true or false we use the value type boolean
. A JSON Schema specifying the type boolean
is given below.
{"type": "boolean"}
This schema will validate only aginst JSON documents true
and false
. Any document of diferent form or of different type, such as "true"
, 42
, or "Number"
, will not satsfy the schema. Note that values that usually evaluate to boolean values in programming languages, such as 0
and 1
are also not permitted.
Formal Specification
A Boolean Schema boolSch is formally specified using the following grammar.
boolSch := "type": "boolean"
Formal Validation
Let B be a Boolean Schema and J a JSON document. We say that J validates against B if:
- J is either true or false
Null Schemas
When specifying that a certain value is missing it is usual to use the type null
. A JSON Schema specifying null values is given below.
{"type": "null"}
This schema will validate aginst JSON document null
and reject all other JSON documents. Therefore documents such as "false"
, false
or 0
will not validate against the schema above.
Formal Specification
A Schema nullSch for null
values is formally specified using the following grammar.
boolSch := "type": "null"
Formal Validation
Let N be a Schema for null
values and J a JSON document. We say that J validates against N if:
- J equals null