Skip to main content

JSON Schema in Practice

Click here if YouTube does not work go to our GitHub.

As we discussed in the previous tutorial, JSON Schema is a declarative format for “describing the structure of other data”. Now we will explain its implementation.

Declaring a JSON Schema

When declaring a JSON Schema, it's important to specify which version of the schema you're using. JSON Schema has several drafts, and distinguishing between them can be challenging. To specify the version, we use the "schema" keyword. WoT uses Draft7, that's why throughout this tutorial we will use Draft7.

{"$schema": "http://json-schema.org/draft-07/schema"}

It is not mandatory, but it is a good practice to specify a unique ID to be able to reach schemas.

{"$id": "http://example.com/temperatureSchema"}

In JSON Schema, an empty object is a completely valid schema that will accept any valid JSON input.

{}

Moreover, it can be used to denote a schema that matches any JSON data, or alternatively, set as false to indicate a schema that doesn't match anything.

empty-json-schema

true-json-schema

The Type Keyword

One of the most useful common things to do in a JSON Schema is to restrict a specific type by using a type keyword.

string-schema

Similar to this, numeric types can also be defined. There are two numeric types in JSON Schema: integer and number and they share the same validation keywords. Number accepts integers and floating-point numbers, while integer specifically excludes floating-point numbers.

number-schema

Objects

In JSON, objects serve as the mapping type, associating "keys" with corresponding "values". Notably, in JSON, the "keys" must always be represented as strings.

{
"type": "object"
}

Properties

The properties which are a key-value pair on an object are defined using the properties keyword. The value of properties is an object, where each key is the name of a property and each value is a schema used to validate that property.

Here is an example JSON Schema defined with the keyword "properties":

{
"type": "object",
"properties": {
"number": { "type": "number" },
"streetName": { "type": "string" }
}
}

This example is accepted by the JSON Schema:

{
"number": 1600,
"streetName": "Boltzmann"
}

Whereas the second one is not accepted because the value of a number is a string:

{
"number": "1600",
"streetName": "Boltzmann"
}

Additional Properties

In addition to the last example, The additionalProperties keyword can be used to control the handling of extra properties whose names are not explicitly listed in the properties keyword. If set to "false", the schema doesn't accept additional properties. Conversely, you can specify the allowed types for additional properties.

A JSON Schema which has the additionalProperties keyword:

"additionalProperties": {
"type": "string"
}

It accepts:

{
"number": 1600,
"streetName": "Boltzmann"
}

And also accepts:

{
"number": "1600",
"streetName": "Boltzmann",
"direction": "NW"
}

Required Properties

By default, the properties defined by the properties keyword are not required. However, one can provide a list of required properties using the required keyword.

Here is an example JSON Schema with the keyword "required":

{
"type": "object",
"properties": {
"name": { "type": "string" },
"email": { "type": "string" },
"address": { "type": "string" },
"telephone": { "type": "string" }
},
"required": ["name", "email"]
}

It accepts:

{
"name": "William Shakespeare",
"email": "bill@tum.de
}

This one is not accepted as it does not contain email information and it is defined as required:

{
"name": "William Shakespeare",
"address": "Henley Street, 80945"
}

Array

Arrays are used for ordered elements. In JSON, each element in an array can be of a different type.

{
"type": "array"
}

This schema accepts:

[3, "different", { "types": "of values" }]

But does not accept this as it is not an array:

{ "Not": "an array" }

Items

The "items" keyword in JSON Schema allows control over whether additional items are permitted in an array. The value of the items keyword is a schema that all additional items must pass for the keyword to validate. It can be set to false, indicating that no additional items are allowed, or it can specify a type for the items in the array.

For example this schema accepts items of type number:

{
"type": "array",
"items": {
"type": "number"
}
}

Therefore accepts:

[1, 2, 3, 4, 5]

But does not accept this as the 3rd element is of type string and not a number:

[1, 2, "3", 4, 5]

Boolean

The Boolean type in JSON Schema only matches two specific values: "true" and "false". It's important to note that other values that might evaluate to true or false, such as 1 and 0, are not considered valid according to the schema.

The JSON Schema with type defined as Boolean can be written as this:

{
"type": "boolean"
}

And it only accepts:

true
false

and does not accept this as the type is not boolean but string:

"true"

Null

When a schema specifies the type of null, it has only one acceptable value: null.

The JSON Schema can be defined as:

{
"type": "null"
}

This schema only accepts:

null

and does not accept others such as:

false
0

ContentMedia Type

The contentMediaType keyword specifies the MIME type of the contents within a string, as described in RFC 2046. If you want to specify any type that is not JSON, it is possible to do so with these content media types.

This schema indicates the string contains an HTML document, encoded using the same encoding as the surrounding document:

{
"type": "string",
"contentMediaType": "text/html"
}

This schema indicates that a string contains a PNG image, encoded using Base64:

{
"type": "string",
"contentEncoding": "base64",
"contentMediaType": "image/png"
}