This is my original tutorial, republished on this website. The examples are preserved. Tool versions and interfaces may have changed.JavaScript Object Notation (JSON) is a simple and lightweight data representational format. And, whenever we talk about data format we also talk about the schema because without a schema, data could mean anything. Let’s take an example.
{
"id": 007,
"name": "John Doe",
"age": 22,
"hobbies": {
"indoor": [
"Chess"
],
"outdoor": [
"Stand-up Comedy"
]
}
}
If you were to look at the above example, you would not necessarily know if id can be zero (0). You would also not know if you could leave age blank. For this reason, we need to have metadata that holds information about valid data types and the description of the keys. And, JSON Schema gives you a standard way to structure the metadata.
What is JSON Schema?
Basic JSON Schema Example
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://example.com/employee.schema.json",
"title": "Record of employee",
"description": "This document records the details of an employee",
"type": "object",
"properties": {
"id": {
"description": "A unique identifier for an employee",
"type": "string"
},
"name": {
"description": "Full name of the employee",
"type": "string"
},
"age": {
"description": "Age of the employee",
"type": "number",
"minimum": 16
},
"hobbies": {
"description": "Hobbies of the employee",
"type": "object",
"properties": {
"indoor": {
"type": "array",
"items": {
"description": "Enter the first hobby",
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"outdoor": {
"type": "array",
"items": {
"description": "Enter the first hobby",
"type": "string"
},
"minItems": 1,
"uniqueItems": true
}
},
"required": [
"indoor",
"outdoor"
]
}
},
"required": [
"id",
"name",
"age",
"hobbies"
]
}
Looks daunting? Let’s break it down to understand further.
JSON Schema keywords and properties
- $schema: states that this schema is written according to the draft v4 specification.
- $id: Defines the base URI to resolve other URI references within the schema.
- title: Describes the intent of the schema.
- description: Gives the description of the schema.
- type: Defines the type of data.
- properties: Defines various keys and their value types within a JSON document.
- minimum: Defines the minimum acceptable value for a numeric datatype.
- items: Enumerates the definition for the items that can appear in an array.
- minItems: Defines the minimum number of items that should appear in an array.
- uniqueItems: Enforces if every item in the array should be unique relative to one another.
- required: Lists the keys that are required and mandatory.
Introduction to JSON in MongoDB Atlas
Starting the Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/product.schema.json",
"title": "Record of Employee",
"description": "This document records the details of an employee",
"type": "object"
}
In the above example, $schema links to the resource that identifies the dialect and the valid schemas written for this dialect.
$id keyword identifies the schema resource. Here are a couple of things to know about this keyword:
- The URI in this keyword is an identifier and not necessarily a network locator.
- It must be a string.
- It must represent a valid URI reference that is normalized and resolves absolute URI.
- It must not contain a non-empty fragment.
- It should not contain an empty fragment.
JSON Schema properties
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://example.com/employee.schema.json",
"title": "Record of employee",
"description": "This document records the details of an employee",
"type": "object",
"properties": {
"id": {
"description": "A unique identifier for an employee",
"type": "string"
}
}
}
Pretty simple and straightforward. You can see we are slowly building our schema by adding properties to validate the JSON documents.
Let's do the same for name and age. But this time, we will also use required and minimum keywords.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://example.com/employee.schema.json",
"title": "Record of employee",
"description": "This document records the details of an employee",
"type": "object",
"properties": {
"id": {
"description": "A unique identifier for an employee",
"type": "string"
},
"name": {
"description": "full name of the employee",
"type": "string"
},
"age": {
"description": "age of the employee",
"type": "number",
"minimum": 16
}
},
"required": [
"id"
"fullName",
"age"
]
}
In the age property, we have used the minimum keyword to ensure that the age of the employee exceeds 16 everytime. We have also used the required keyword to define the mandatory properties. Let’s take it a step further and add an object inside the employee object.
Nesting data structures
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://example.com/employee.schema.json",
"title": "Record of employee",
"description": "This document records the details of an employee",
"type": "object",
"properties": {
"id": {
"description": "A unique identifier for an employee",
"type": "string"
},
"name": {
"description": "name of the employee",
"type": "string"
},
"age": {
"description": "age of the employee",
"type": "number",
"minimum": 16
},
"hobbies": {
"description": "hobbies of the employee",
"type": "object",
"properties": {
"indoor": {
"type": "array",
"items": {
"description": "Enter your hobby",
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"outdoor": {
"type": "array",
"items": {
"description": "Enter your hobby",
"type": "string"
},
"minItems": 1,
"uniqueItems": true
}
},
"required": [
"indoor",
"outdoor"
]
}
},
"required": [
"id",
"fullName",
"age",
"hobbies"
],
"additionalProperties": false
}
In the above example, we have defined two arrays - indoor and outdoor. You might have noticed the items keyword. This keyword defines the properties of each item within an array.
Similarly, minItems keyword defines the minimum number of items that must be present in the array and uniqueItems keyword tells us if the items in the array are unique relative to each other.
You will also see the required keyword again within the subobject. Like the required keyword in the root object, the required keyword within the subobject dictates the mandatory properties within the subobjects.Lastly, we have also introduced the additionalProperties keyword. In the above example, it is a boolean taking the value false and is telling us that we can not use any other properties that are not listed under the properties keyword. However, additionalProperties don’t necessarily have to be a boolean. It can also be an object. For example, in the schema below, this keyword is stating that any additional property that we use under this schema has to be a string.
"additionalProperties": { "type": "string" }
Using Your Schema for Validation in MongoDB Atlas
Using JSON Schema for Geographical Coordinates
{
"latitude": 58.858093,
"longitude": 22.294694
}
But there is a limit to the value that we can use for a coordinate i.e., the values cannot be more than 90 or less than negative 90. So let’s create a JSON schema to address this scenario.
{
"$id": "https://example.com/geographical-location.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Longitude and Latitude Values",
"description": "A geographical coordinate.",
"required": [ "latitude", "longitude" ],
"type": "object",
"properties": {
"latitude": {
"type": "number",
"minimum": -90,
"maximum": 90
},
"longitude": {
"type": "number",
"minimum": -180,
"maximum": 180
}
}
}
Here you can see that we have used the minimum and maximum keyword for each property to limit the range of acceptable values. This not only resolves the issue with data validation but also ensures that incorrect values do not get through.
To Sum It Up
Original
JSON Schema Examples
What is JSON?
{
"id": "007",
"fullName": "John Doe",
"age": 22,
"position": "Web Developer",
"company": "MongoDB",
"hobbies": {
"indoor": [
"Chess"
],
"outdoor": [
"Stand-up Comedy"
]
}
}
What is JSON schema?
JSON Schema Example
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://example.com/employee.schema.json",
"title": "Record of employee",
"description": "This document records the details of an employee",
"type": "object",
"properties": {
"id": {
"description": "A unique identifier for an employee",
"type": "string"
},
"fullName": {
"description": "fullname of a person",
"type": "string"
},
"age": {
"description": "age of a person",
"type": "number",
"minimum": 16
},
"position": {
"description": "position of a person",
"type": "string"
},
"company": {
"description": "the name of the company where the person works",
"type": "string"
},
"hobbies": {
"description": "hobbies of the person",
"type": "object",
"properties": {
"indoor": {
"type": "array",
"items": {
"description": "Enter the first hobby",
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"outdoor": {
"type": "array",
"items": {
"description": "Enter the first hobby",
"type": "string"
},
"minItems": 1,
"uniqueItems": true
}
},
"required": [
"indoor",
"outdoor"
]
}
},
"required": [
"id",
"fullName",
"age",
"position",
"company",
"hobbies"
]
}
This can seem a bit daunting. Let’s break it down and understand further.
JSON schema Keywords and properties {#json-schema-keywords-and-properties}
- $schema: This keyword states that this schema is written according to the draft v4 specification.
- $id: This keyword defines a URI for the schema and the base URI that other URI references within the schema are resolved against.
- title: This keyword is descriptive only as it does not add constraints to the data being validated. The intent of the schema is stated with the keyword title.
- description: This keyword is used alongside the keyword title for description.
- type: This keyword defines the first constraint on our JSON data. For this file, it must be a JSON Object.
- properties: This keyword defines various keys and their value types.
- required: This keyword keeps a list of required properties.
How do I create a JSON schema?
- $schema: For standard and version control
- $id: for URI for the schema, and the base URI that other URI references within the schema are resolved against.
- title: to state the intent of the schema
- description: give a description of the schema
- type: to put a constraint on our JSON data. For this file, it must be a JSON Object.
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/employee.schema.json",
"title": "Record of employee",
"description": "This document records the details of an employee",
"type": "object"
}
JSON schema properties
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://example.com/employee.schema.json",
"title": "Record of employee",
"description": "This document records the details of an employee",
"type": "object",
"properties": {
"id": {
"description": "A unique identifier for an employee",
"type": "string"
}
}
}
Now, we use the keywords required, minimum to add constraints to our schema.
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://example.com/employee.schema.json",
"title": "Record of employee",
"description": "This document records the details of an employee",
"type": "object",
"properties": {
"id": {
"description": "A unique identifier for an employee",
"type": "string"
},
"fullName": {
"description": "full name of a person",
"type": "string"
},
"age": {
"description": "age of a person",
"type": "number",
"minimum": 16
}
},
"required": [
"id"
"fullName",
"age"
]
}
As you can see, we are slowly building our schema by adding various properties. Properties are used to validate the JSON documents that we create. You can add more properties like boolean, enum to add more constraints based on the data type you require.
Nesting data structures
{
"$schema": "http://json-schema.org/draft-04/schema#",
"$id": "https://example.com/employee.schema.json",
"title": "Record of employee",
"description": "This document records the details of an employee",
"type": "object",
"properties": {
"id": {
"description": "A unique identifier for an employee",
"type": "string"
},
"fullName": {
"description": "fullname of a person",
"type": "string"
},
"age": {
"description": "age of a person",
"type": "number",
"minimum": 16
},
"position": {
"description": "position of a person",
"type": "string"
},
"company": {
"description": "the name of the company where the person works",
"type": "string"
},
"hobbies": {
"description": "hobbies of the person",
"type": "object",
"properties": {
"indoor": {
"type": "array",
"items": {
"description": "Enter your hobby",
"type": "string"
},
"minItems": 1,
"uniqueItems": true
},
"outdoor": {
"type": "array",
"items": {
"description": "Enter your hobby",
"type": "string"
},
"minItems": 1,
"uniqueItems": true
}
},
"required": [
"indoor",
"outdoor"
]
}
},
"required": [
"id",
"fullName",
"age",
"position",
"company",
"hobbies"
],
"additionalProperties": false
}
As you can see, we have added constraints for hobbies within the nested data structure.Lastly, we added additionalProperties: false as we don’t want additional information to be added to the JSON file.
Using Your Schema for Validation
A few more examples: JSON Nested Array Schema
{
"name":"John",
"age":30,
"cars": [
{ "name":"Ford", "models":[ "Fiesta", "Focus", "Mustang" ] },
{ "name":"BMW", "models":[ "320", "X3", "X5" ] },
{ "name":"Fiat", "models":[ "500", "Panda" ] }
]
}
Schema
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"age": {
"type": "integer"
},
"cars": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"models": {
"type": "array",
"items": [
{
"type": "string"
},
{
"type": "string"
},
{
"type": "string"
}
]
}
},
"required": [
"name",
"models"
]
},
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"models": {
"type": "array",
"items": [
{
"type": "string"
},
{
"type": "string"
},
{
"type": "string"
}
]
}
},
"required": [
"name",
"models"
]
},
{
"type": "object",
"properties": {
"name": {
"type": "string"
},
"models": {
"type": "array",
"items": [
{
"type": "string"
},
{
"type": "string"
}
]
}
},
"required": [
"name",
"models"
]
}
]
}
},
"required": [
"name",
"age",
"cars"
]
}
A few more examples: For Geographical Coordinates
{
"latitude": 58.858093,
"longitude": 22.294694
}
Schema
{
"$id": "https://example.com/geographical-location.schema.json",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"title": "Longitude and Latitude Values",
"description": "A geographical coordinate.",
"required": [ "latitude", "longitude" ],
"type": "object",
"properties": {
"latitude": {
"type": "number",
"minimum": -90,
"maximum": 90
},
"longitude": {
"type": "number",
"minimum": -180,
"maximum": 180
}
}
}