JSON Schema is a declarative way of writing validation rules. It contains all the steps that are necessary to be performed in order to validate something. The format used to write these steps is, of course, JSON itself.

Opis JSON Schema is the software/library (for PHP) that performs those steps and tells you the validation status.

Data types

Because JSON Schema is written in JSON format, it supports all JSON types plus an addition: the integer type, which is a subtype of the number type.

  • string - represents a string/text, e.g. "a string", "other string"
  • number - represents an integer or a float, e.g. -5, 10, -5.8, 10.2
  • integer - represents an integer, e.g. -100, 125, 0
  • boolean - represents a boolean value, e.g. true or false
  • null - indicates that a value is missing, e.g. null
  • object - a key-value map, where the key must be a string and the value can be any type, e.g. {"key": "value", "other-key": 5}
  • array - an ordered list of any data types, e.g. [1, -2.5, "some string", null]

Document structure

A valid json schema document must be a JSON object or a boolean value. If it is a boolean, then the validation status is indicated by the value of the boolean: true - valid, false - invalid. If it is an object, then it must contain the steps needed for validation. These steps come in the form of keywords and every keyword has a specific meaning. Keywords are applied to data starting from the root of the document schema and descend to their children.

Here are some examples

true
false
{}
{
  "type": "string"
}
Input Status
"test" valid
123 invalid

Some keywords are purely decorative, like metadata keywords, which just describe the author intent. Others are for identifying a document or a subschema, and the rest of them are for validity checks. Usually keywords work independently and there are only a few exceptions.

$schema keyword

This keyword is used to specify the desired schema version. The value of this keyword must be a string representing an URI.

Currently the supported URIs are:

  • https://json-schema.org/draft/2020-12/schema - latest version
  • https://json-schema.org/draft/2019-09/schema - previous version
  • http://json-schema.org/draft-07/schema#
  • http://json-schema.org/draft-06/schema#

This keyword is not required and if it is missing, the URI of the latest schema version will be used instead.

Not all keywords all available on all drafts, so we recommend using this keyword to set the right context.

$id keyword

This keyword is used to specify an unique ID for a document or a document subschemas. The value of this keyword must be a string representing an URI. All subschema IDs are resolved relative to the document’s ID. It is not a required keyword, but we recommend you using it, as a best practice.

The usage of this keyword will be covered in the next chapters.

$anchor keyword

This keyword is used to define fragment identifiers.

The two schemas below are equivalent.

{
 "$id": "http://example.com",
 
 "$ref": "#mail",
 
 "$defs": {
  "mail": {
   "$anchor": "mail",
   "format": "email"
  }
 }
}
{
 "$id": "http://example.com",

 "$ref": "#mail",
 
 "$defs": {
  "mail": {
   "$id": "#mail",
   "format": "email"
  }
 }
}

definitions keyword

This keyword does not directly validate data, but it contains a map of validation schemas. The value of this keyword can be anything. This keyword is not required.

$defs keyword

Same as definitions keyword (standardized staring with draft-2019-09).

Metadata keywords

These keywords are not used for validation, but to describe the validation schema and how it works. All keywords are optional.

title

Contains a short description about the validation. The value of this keyword must be a string.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "http://example.com/number.json#",
  "title": "Test if it is a number",
  
  "type": "number"
}

description

Contains a long description about the validation. The value of this keyword must be a string.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "http://example.com/number.json#",
  "title": "Test if it is a number",
  "description": "A data is considered number if it is an integer or a float.",
  
  "type": "number"
}

examples

Contains a list of valid examples. The value of this keyword must be an array.

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "http://example.com/number.json#",
  "title": "Test if it is a number",
  "description": "A data is considered a number if is an integer or a float.",
  "examples": [-5.10, -2, 0, 5, 8.10],
  
  "type": "number"
}

$comment

Contains an observation about the schema. The value of this keyword must be a string.

{
  "$comment": "We should replace this broken regex with format: email.",
  
  "type": "string",
  "pattern": "[a-zA-Z0-9\\.]+@[a-zA-Z0-9]+\\.[a-zA-Z]{2,3}"
}

JSON Schema examples

For most of the basic examples we will not use $schema, $id and metadata keywords.

Don’t worry if you don’t exactly understand every keyword, they are presented in depth in the next chapters.

Validating a simple user

{
  "type": "object",
  "properties": {
    "name": {
      "type": "string"
    },
    "email": {
      "type": "string",
      "format": "email"
    },
    "age": {
      "type": "integer",
      "minimum": 18,
      "maximum": 150
    }
  },
  "required": ["email"]
}
Input Status
{"name": "John", "email": "john@example.com", "age": 25} valid
{"email": "john@example.com"} valid - only the email is required
{"name": "John", "age": 25} invalid - required email is missing
{"name": "John", "email": "john(at)example.com", "age": 25} invalid - not a valid email address
{"email": 123} invalid - email must be a string
{"email": "john@example.com", "age": 25.5} invalid - age must be an integer
"john@example.com" invalid - must be an object

Validating a list

{
  "type": "array",
  "minItems": 2,
  "items": {
    "type": ["string", "number"]
  }
}
[1, "a"] valid
[-5.1, 10.8, 2] valid
["a", "b", "c", "d", 4, 5] valid
[1] invalid - must have at least 2 items
["a", {"x": 1}] invalid - contains an object
{"0": 1, "1": 2} invalid - not an array