How JSON_SCHEMA_VALID() Works in MySQL

In MySQL, the JSON_SCHEMA_VALID() function validates a JSON document against a JSON schema. It returns true (1) if the document is valid, and false (0) if it is not.

Syntax

The syntax goes like this:

JSON_SCHEMA_VALID(schema,document)

Where schema is the JSON schema, and document is the JSON document that we want to check against that schema.

Example

Here’s an example to demonstrate:

SET @schema = '{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/product.schema.json",
  "title": "Product",
  "description": "A product from the catalog",
  "type": "object",
  "properties": {
    "productId": {
      "description": "The unique identifier for a product",
      "type": "integer"
    },
    "productName": {
      "description": "Name of the product",
      "type": "string"
    },
    "price": {
      "description": "The price of the product",
      "type": "number",
      "exclusiveMinimum": 0
    }
  },
  "required": [ "productId", "productName", "price" ]
}';

SET @document = '{
    "productId": 1,
    "productName": "Left-handed screwdriver",
    "price": 250
    }';

SELECT JSON_SCHEMA_VALID(@schema, @document);

Result:

1

In this case the JSON document is valid and we get a result of 1.

Invalid JSON Document

Here’s what happens when the JSON document is not valid:

SET @schema = '{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/product.schema.json",
  "title": "Product",
  "description": "A product from the catalog",
  "type": "object",
  "properties": {
    "productId": {
      "description": "The unique identifier for a product",
      "type": "integer"
    },
    "productName": {
      "description": "Name of the product",
      "type": "string"
    },
    "price": {
      "description": "The price of the product",
      "type": "number",
      "exclusiveMinimum": 0
    }
  },
  "required": [ "productId", "productName", "price" ]
}';

SET @document = '{
    "productId": 1,
    "productName": "Left-handed screwdriver"
    }';

SELECT JSON_SCHEMA_VALID(@schema, @document);

Result:

0

In this case, I removed the price from the JSON document and so the JSON document is no longer valid.

The reason the JSON document is not valid is because the schema states that the price field is required. In fact it states that all three fields are required.

But even when a field exists in the JSON document, it still needs to adhere to any rules set by the schema.

In the following example I put the price field back into the document, but I give it a value that doesn’t adhere to the schema:

SET @schema = '{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.com/product.schema.json",
  "title": "Product",
  "description": "A product from the catalog",
  "type": "object",
  "properties": {
    "productId": {
      "description": "The unique identifier for a product",
      "type": "integer"
    },
    "productName": {
      "description": "Name of the product",
      "type": "string"
    },
    "price": {
      "description": "The price of the product",
      "type": "number",
      "exclusiveMinimum": 0
    }
  },
  "required": [ "productId", "productName", "price" ]
}';

SET @document = '{
    "productId": 1,
    "productName": "Left-handed screwdriver",
    "price": "Two Hundred and Fifty"
    }';

SELECT JSON_SCHEMA_VALID(@schema, @document);

Result:

0

Once again we get a return value of 0. This is because the price field contains a string value instead of a number. The JSON schema specifies that the field must contain a number, and so the JSON document is invalid.

Using JSON_SCHEMA_VALID() with CHECK Constraints

We can use the JSON_SCHEMA_VALID() function to enforce CHECK constraints.

If we have a JSON column in our database, we can create a CHECK constraint that validates any data that is to be stored in that column. In such cases, we can use the JSON_SCHEMA_VALID() function to check that the value adheres to the JSON schema.

Example:

CREATE TABLE stats (
    scores JSON,
    CHECK(
        JSON_SCHEMA_VALID(
            '{
                "type": "object",
                "properties": {
                "playerId": {
                "description": "The unique identifier for a player",
                "type": "integer"
                },
                "playerName": {
                "description": "Name of the player",
                "type": "string"
                },
                    "score": {
                    "description": "The price of the product",
                    "type": "integer",
                     "minimum": 0,
                     "maximum": 500
                    }
                },
                "required": [ "playerId", "playerName", "score" ]
            }',
            scores
        )
    )
);

That code created a table called stats with a JSON column called scores.

We created a CHECK constraint that uses JSON_SCHEMA_VALID() to check any JSON document that’s inserted into the column. Basically, we check that the JSON document contains all three fields, that their data type is correct, and that the score field contains a value between 0 and 500.

Now let’s insert data into the table:

INSERT INTO stats ( scores ) 
    VALUES (
        '{
            "playerId" : 1,
            "playerName" : "Bart",
            "score" : 427
        }'
    );

Now let’s take a look at the contents of our table:

SELECT * FROM stats;

Result:

+-----------------------------------------------------+
| scores                                              |
+-----------------------------------------------------+
| {"score": 427, "playerId": 1, "playerName": "Bart"} |
+-----------------------------------------------------+

In this case the JSON was valid against the schema, and it was therefore inserted into the table.

Let’s try to insert a JSON document that violates the schema:

INSERT INTO stats ( scores ) 
    VALUES (
        '{
            "playerId" : 2,
            "playerName" : "Homer",
            "score" : -500
        }'
    );

Result:

ERROR 3819 (HY000): Check constraint 'stats_chk_1' is violated.

In this case our JSON document violated the schema. Specifically, this player has a negative score, but negative scores aren’t allowed.