JSON Schema

JSON Schema#

A JSON schema declares the expected format of a JSON document.

Regular JSON is human-readable, but it doesn’t include any context or metadata. JSON Schema enables information about the meanings of the keys and the possible values they can take.

It is a popular method for documenting and validating JSON files.

For more check the documentation of JSON schema.

A JSON Schema is a standard used to define and validate the structure and data types of a JSON document (the instance). It is itself a JSON document where the structure and constraints for each property are described using predefined schema keywords (e.g., type, properties).

For examples chema:

#schema
{"type": "number"}

Specifies the the root level of the JSON should be a number, e.g. JSON by itself a number.

10
ok -- validation done

The following cell specifies that the root object is a mapping. The available attributes of the root mapping are specified in the properties of the JSON schema.

#schema
{
    "type": "object",
    "properties":
    {
        "wow": {
            "type": "string"
        }
    }
}
{"wow": "value"}
Schema validation errors were encountered.
  object.json::$: {'wow': 'value'} is not of type 'number'

Type#

The type keyword is used to specify the type of the attribute.

Check more in Type-specified Keywords.


The following cell indicates that the root element of the JSON should be a string.

#schema
{"type": "string"}

Specifying a string works fine.

"some string"
ok -- validation done

However, any other object, such as number, will result in the corresponding error.

10
Schema validation errors were encountered.
  object.json::$: 10 is not of type 'string'

Arrays#

An array is used to list elements. Find out more about arrays in JSON schemas on the Array reference page.

Use the following schema keywords to define what the items array can contain:

  • items: This sepecifies the schema to which each item in the list must correspond. Such approach is called List validation.

  • prefixItems: peforms the tuple validation where the order of items is important and each item has a different schema.

  • contains: specifies the rule to which at least one element of the array have to correspond.

Note: You can combine items with different specifications for the same array.


The following cell defines the schema for array for which:

  • items: sets up that array can contains only numbers 1, 2, 3.

  • contains: defines that it have to contain at least one entrance of 2.

#schema
{
    "type": "array",
    "items": {
        "enum": [1, 2, 3]
    },
    "contains": {
        "const": 2
    }
}

The array [3, 3, 2] is fine because it contains elements defined in the contains and does not contain elements that are not mentioned in the items.

[3, 3, 2]
ok -- validation done

The case where the item 2 is not present is validated in the following cell.

[1, 1, 1, 3]
Schema validation errors were encountered.
  object.json::$: [1, 1, 1, 3] does not contain items matching the given schema

The case where the array under consideration contains a value that is not mentioned in the items is represented in the following cell.

[1, 4, 2]
Schema validation errors were encountered.
  object.json::$[1]: 4 is not one of [1, 2, 3]

Set#

It is a typical requirement to specify an array containing all the elements from a given set of elements and not others. To specify such a combination use:

  • items to specify set of the available items.

  • contains for each element joined in the "allOf" boolean composition: to specify that each element must appear in the input at least once.

Unlike the prefixItems, such approach allows to ignore the order of the elements.


The following cell specifies the JSON schema specifies the array that contains elements {1, 2, 3} items and only them.

#schema
{
  "type": "array",
  "items": { "enum": [1, 2, 3] },
  "allOf": [
    { "contains": { "const": 1 } },
    { "contains": { "const": 2 } },
    { "contains": { "const": 3 } }
  ]
}

The following cells show that the order of the elements in the array does not matter if the objects are present.

[2, 3, 1]
ok -- validation done

The validation error if some elements are missing:

[1, 2]
Schema validation errors were encountered.
  object.json::$: [1, 2] does not contain items matching the given schema

If there is unexpected element:

[1, 2, 3, 4]
Schema validation errors were encountered.
  object.json::$[3]: 4 is not one of [1, 2, 3]

Note this approach doesn’t take into account duplicates.

[1, 2, 2, 3]
ok -- validation done

Composition#

You can combine different schemas to create a complex validation algorithms. There are two concepts:

  • Modular: allows to reuse defined schemas in other schemas.

  • Boolean: you can specify a schema that validates the input against several schemas joined by logical operations.

Check more in Schema Composition page.

Boolean#

Boolean compositions allow you to validate input against multiple sub-schemas and define the rules for how the data must satisfy those schemas. A set of keywords that allows to validation logic to be defined:

  • allOf: the input have to satisfy all composed schemas (AND).

  • anyOf: the input have to satisfy at least one of composed schemas (OR).

  • oneOf: the input have to satisfy exactly one of composed schemas (XOR).

  • not: the input have to not satisfy the given input.


The following cell defines the schema that inusres the input is an object with exactly specified values.

#schema
{
    "type": "object",
    "anyOf": [
        {
            "properties": {
                "user": {"const": "Fedor"},
                "job": {"const": "Programmer"}
            },
            "required": ["user", "job"]
        },
        {
            "properties": {
                "user": {"const": "Natalia"},
                "job": {"const": "Chemist"}
            },
            "required": ["user", "job"]
        }
    ]
}

Everything goes fine when you specify mappings mentioned in anyOf.

{
    "user": "Fedor",
    "job": "Programmer"
}
ok -- validation done
{
    "user": "Natalia",
    "job": "Chemist" 
}
ok -- validation done

However, validation will fail if you specify a different object.

{
    "user": "Igor",
    "job": "Physicist" 
}
Schema validation errors were encountered.
  object.json::$: {'user': 'Igor', 'job': 'Physicist'} is not valid under any of the given schemas
  Underlying errors caused this.

  Best Match:
    $.user: 'Fedor' was expected

  3 other errors were produced. Use '--verbose' to see all errors.

Modularity#

The JSON Schema syntax enables reusable JSON structures to be specified and referenced by other structures. These structures can be defined in external JSON Schema files or within the same file.

The following keys are used to define and reference other schemas:

  • $id: Defines the URI used to identify this root schema.

  • $anchor: Defines a specific subschema location that can be referenced by a fragment identifier.

  • $defs: A mapping key where other subschemas are defined so they can be referenced.

  • $ref: Indicates that the current element should be validated against the schema at the specific URI provided in the value.

Learn more on the Modular JSON Schema Validation page.


The following cell defines the JSON schema that defines "PC" and "Server" attributes both of which require one of "windows", "linux", "freeBSD".

#schema
{
    "type": "object",
    "properties": {
        "PC": {"$ref": "#/$defs/system"},
        "Server": {"$ref": "#/$defs/system"}
    },
    "$defs": {
        "system": {"enum": ["windows", "linux", "freeBSD"]}
    }
}

Note: for some reason, check-jsonschema doesn’t work with references. Try using the JSON schema validator.