EVENTGet 50% off your ticket to MongoDB.local NYC on May 2. Use code Web50! Learn more >

JSON Schema Examples Tutorial

To follow along with this tutorial, you'll need a MongoDB Atlas account and to download MongoDB Compass.

JSON (JavaScript Object Notation) is a simple and lightweight text-based data format. JSON Schema is an IETF standard providing a format for what JSON data is required for a given application and how to interact with it. Applying such standards for a JSON document lets you enforce consistency and data validity across similar JSON data.

.Let's take a look at a document example with a person's name and their indoor and outdoor hobbies.

{
  "id": 7,
  "name": "John Doe",
  "age": 22,
  "hobbies": {
        "indoor": [
            "Chess"
        ],
        "outdoor": [
            "BasketballStand-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. Additionally, JSON Schema gives you a standard way to structure the metadata.

Basic JSON Schema Example

Let’s look at an example of a JSON Schema for the above document type.

{
    "$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": "number"
        },
        "name": {
            "description": "Full name of the employee",
            "type": "string"
        },
        "age": {
            "description": "Age of the employee",
            "type": "number"
        },
        "hobbies": {
            "description": "Hobbies of the employee",
            "type": "object",
            "properties": {
                "indoor": {
                    "type": "array",
                    "items": {
                        "description": "List of indoor hobbies",
                        "type": "string"
                    }
                },
                "outdoor": {
                    "type": "array",
                    "items": {
                        "description": "List of outdoor hobbies",
                        "type": "string"
                    }
                }
            }
        }
    }
}

It could look daunting at first glance but we will break it down to understand further.

JSON Schema Keywords and Properties

We have different keywords that are used in the above example. The following list explains what each of these keywords mean.

  • $schema: States that this schema complies with v4 of the IETF standard
  • $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.

For a full list of keywords, visit json-schema.org. The link explains the keywords that you can use in your schema and their purpose.

How do I create a JSON schema?

You can use online JSON schema generators if you have a simple JSON document, then modify the schema as per the requirement of your project. Alternatively, you can build a JSON schema of your own from scratch by following the steps below

Starting the Schema

If you have already familiarized yourself with the JSON schema keywords and properties, we can jump right into starting a basic JSON schema. Lets begin with five basic keywords to define an employee.

Base 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.

title keyword gives a short description of the schema and you can use the description keyword to explain more about the schema. In the above example, the title hints that this schema is about a record of an employee and the description explains that in detail.

type keyword explains the valid data type of a record. In the above example, type sets the constraint for this document and tells us that this record is an object.

JSON Schema Properties

The Entry Schema

The schema that we have used in the above section is a basic outline. Lets build on it by adding an id field to the employee record.

{
    "$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": "number"
        }
    }
}

We have added two sub-properties, “id.description”, stating that it is a unique identifier, and “id.type”, explaining that it is a number.

Let's do the same for name and age -- but this time, with new 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"
            "minLength":2
        },
        "age": {
            "description": "age of the employee",
            "type": "number",
            "minimum": 16
        }
    },
    "required": [
        "id"  
        "name",
        "age"
    ]
}

In the name property, we have introduced the minLength keyword to make sure that the property has at least two characters. Similarly, in the age property, we have used the minimum keyword to ensure that the age of the employee exceeds 16 everytime. It can be of type number or type integer. We have also used the required keyword to define the mandatory properties. Now, let’s take it a step further and add an object inside the employee object.

Nesting Data Structures

To add an object inside an object in JSON format, we use nested data structure. Creating subschemas for Nested objects work quite similarly to the creating schemas for root objects. You can use all the schema keywords that you used when defining the root object except for $schema and $id. They only have to be stated at the beginning of a schema.

Arrays of Things

The following example shows how we can create an object within an object that takes an array type data. Here, we will use a few new keywords in addition to the ones we have already used.

{
    "$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": "number"
        },
        "name": {
            "description": "name of the employee",
            "type": "string",
            "minLength":2
        },
        "age": {
            "description": "age of the employee",
            "type": "number",
            "minimum": 16
        },
        "hobbies": {
            "description": "hobbies of the employee",
            "type": "object",
            "properties": {
                "indoor": {
                    "type": "array",
                    "items": {
                        "description": "List of hobbies",
                        "type": "string"
                    },
                    "minItems": 1,
                    "uniqueItems": true
                },
                "outdoor": {
                    "type": "array",
                    "items": {
                        "description": "List of hobbies",
                        "type": "string"
                    },
                    "minItems": 1,
                    "uniqueItems": true
                }
            },
            "required": [
                "indoor",
                "outdoor"
            ]
        }
    },
    "required": [
        "id",
        "name",
        "age",
        "hobbies"
    ],
 "additionalProperties": false
}

In the above example, we have defined two array fields - indoor and outdoor in the “hobbies” object. You might have noticed the items keyword. This keyword defines the properties of each item.

Similarly, minItems defines the minimum number of items that must be present in the array, maxItems defines the maximum number of items that can be present within the array uniqueItems uniquely identifies each item.

You will also see the required keyword again within the subobject. Like the required keyword in the root JSON object, the required keyword within the subobject dictates the mandatory properties within the subobjects.

Lastly, we have also introduced additionalProperties. In the above example, it is a boolean taking the value false , telling us that we can’t use any other property that isn’t listed under the properties keyword.

However, additionalProperties doesn’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 is required to be of type string.

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

Describing Geographical Coordinates

Though the above example is limited to a use case, there are limitless uses of JSON schema. One of the areas where JSON schema can be used to validate and enforce consistency is with geographical coordinates. Because of the nature of the data, there is a high chance of accepting invalid or inconsistent data.

In the example below, we can see that coordinates are represented using numeric data types.

{
  "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.

Using Your Schema for Validation in MongoDB Atlas

You can use $jsonSchema in a document validator to enforce the specified schema on insert and update operations in MongoDB, including in MongoDB Atlas. Since MongoDB stores the data in BSON (Binary JSON), you can easily store and retrieve all your data in JSON format.

MongoDB also lets you enforce a schema to validate your data and maintain a data structure. We will use MongoDB Atlas and MongoDB Compass to demonstrate how.

Suppose we insert the following documents into a collection named employees inside a database named mongodatabase.

Document 1

{
    "id": 7,
    "name": "John Doe",
    "age": 22,
    "hobbies": {
        "indoor": [
            "Chess"
        ],
        "outdoor": [
            "Basketball"
        ]
    }
}

Document 2

{
     "id": 8,
     "name": "Jonathon Smith",
     "age": 22
}

Document 3

{
    "id": 1,
    "name": "Jane Doe",
    "age": 25,
    "hobbies": {
        "indoor": [
            "Chess"
        ],
        "outdoor": [
            "Football"
        ]
    }
}

Connect our cluster to MongoDB Compass We will enforce the schema from the previous section to validate these documents in MongoDB Compass.

Firstly, let’s connect our cluster with our Compass.

  • Log into MongoDB Atlas and click Clusters
  • Click on CONNECT to connect with your cluster.
  • Set up connection security by adding your IP address and creating a database user. Then select Choose a connection method.
  • Select Connect using MongoDB Compass.
  • Download MongoDB Compass if you have not already and copy the connection string.
  • Open MongoDB Compass and paste the connection string. Your connection string should look similar to this:
mongodb+srv://<username>:<password>@cluster0.9ddm0.mongodb.net/test

Replace <username> and <password> with the username and password of the database user that you created.

select mongodatabase

Now, let’s go into the mongodatabase and look at the documents inside the employees collection.

select employees

Click on the Validation tab and insert the following JSON schema to validate our documents. Begin the schema definition with $jsonSchema keyword. Because we don’t need the $id and $schema keywords to get started, we will remove them.

{
  $jsonSchema: {
    "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": "number"
        },
        "name": {
            "description": "name of the employee",
            "type": "string",
            "minLength":2
        },
        "age": {
            "description": "age of the employee",
            "type": "number",
            "minimum": 16
        },
        "hobbies": {
            "description": "hobbies of the employee",
            "type": "object",
            "properties": {
                "indoor": {
                    "type": "array",
                    "items": {
                        "description": "List of hobbies",
                        "type": "string"
                    },
                    "minItems": 1,
                    "uniqueItems": true
                },
                "outdoor": {
                    "type": "array",
                    "items": {
                        "description": "List of hobbies",
                        "type": "string"
                    },
                    "minItems": 1,
                    "uniqueItems": true
                }
            },
            "required": [
                "indoor",
                "outdoor"
            ]
        }
    },
    "required": [
        "id",
        "name",
        "age",
        "hobbies"
    ],
 "additionalProperties": false
}
}

If you have followed the steps so far, you should get the following result. sample document validation results

As our schema requires a hobbies field in every document, the document with the id: 8 fails because it didn’t contain the required field.

You can also set additional validation rules by following the documentation on setting validation rules for your schema. To match documents that satisfy the specified JSON Schema, you can use the $jsonSchema operator. The MongoDB JSON Schema documentation is an excellent resource to get you up and running.

To learn more about MongoDB Atlas, refer to this article.

Next Steps

By now, you should understand the JSON Schema, why it is used, and how we can use it. We have certainly expanded on the concept and how you can use it with MongoDB but there is more to cover.

If you want to learn more about JSON Schema with MongoDB, we recommend you go through MongoDB’s JSON Schema validation resource. If you are interested in knowing more about JSON Schema validation generally, visit this article.

FAQs

What is JSON Schema?

JSON Schema is a model that represents the format and structure of a common group of JSON documents.

What is the use of JSON Schema?

We use JSON Schema to enforce consistency and data validity across JSON documents.

How do I create a JSON Schema?

You can use online JSON Schema generators or create one on your own by implementing relevant schema structure, keywords, and properties.

Is JSON Schema an industry standard for defining JSON structure?

Yes. JSON Schema is considered to be a standard way to enforce JSON structure validity.

Where should I submit the $jsonSchema data?

You submit the $jsonSchema data using either a shell command or in MongoDB Compass. Once submitted, MongoDB stores this data together with the collection’s metadata.