MariaDB JSON_EXTRACT() Explained

In MariaDB, JSON_EXTRACT() is a built-in function that extracts data from a JSON document, based on a given path or paths.

It can return single values and multiple values. If a single value is matched, a single value is returned. If multiple values are matched, then those values are returned in an array.

Syntax

The syntax goes like this:

JSON_EXTRACT(json_doc, path[, path] ...)

Where json_doc is the JSON document, and each path argument is a path within the document.

Example

Here’s an example to demonstrate.

SET @json_document = '
    { 
        "name": "Wag", 
        "type": "Dog", 
        "weight": 20 
    }
';
SELECT JSON_EXTRACT(@json_document, '$.name');

Result:

+----------------------------------------+
| JSON_EXTRACT(@json_document, '$.name') |
+----------------------------------------+
| "Wag"                                  |
+----------------------------------------+

Multiple Paths

Here’s an example of specifying multiple paths in order to return multiple values from the JSON document.

When you return multiple values, they are returned in an array.

SET @json_document = '
    { 
        "name": "Wag", 
        "type": "Dog", 
        "weight": 20 
    }
';
SELECT JSON_EXTRACT(@json_document, '$.name', '$.weight');

Result:

+----------------------------------------------------+
| JSON_EXTRACT(@json_document, '$.name', '$.weight') |
+----------------------------------------------------+
| ["Wag", 20]                                        |
+----------------------------------------------------+

Non-Existent Paths

Passing a path that doesn’t exist in the JSON document results in NULL.

Example:

SET @json_document = '
    { 
        "name": "Wag", 
        "type": "Dog", 
        "weight": 20 
    }
';
SELECT JSON_EXTRACT(@json_document, '$.color');

Result:

+-----------------------------------------+
| JSON_EXTRACT(@json_document, '$.color') |
+-----------------------------------------+
| NULL                                    |
+-----------------------------------------+

However, if multiple paths are passed, and at least one of them matches, then the matching value is extracted and returned in an array. This is true even if only one value is extracted.

Example:

SET @json_document = '
    { 
        "name": "Wag", 
        "type": "Dog", 
        "weight": 20 
    }
';
SELECT JSON_EXTRACT(@json_document, '$.name', '$.color');

Result:

+---------------------------------------------------+
| JSON_EXTRACT(@json_document, '$.name', '$.color') |
+---------------------------------------------------+
| ["Wag"]                                           |
+---------------------------------------------------+

Arrays

Here’s an example of extracting data from an array:

SET @json_document = '
    { 
        "_id" : 1, 
        "awards" : [ "Top Dog", "Best Dog", "Biggest Dog" ] 
    }
';
SELECT JSON_EXTRACT(@json_document, '$.awards[0]');

Result:

+---------------------------------------------+
| JSON_EXTRACT(@json_document, '$.awards[0]') |
+---------------------------------------------+
| "Top Dog"                                   |
+---------------------------------------------+

Arrays are zero-based, and so $.awards[0] extracts the first element of the awards array.

Nested Objects

Here’s an example of extracting data from an object nested inside another object:

SET @json_document = '
    { 
        "_id" : 1, 
        "name" : "Wag", 
        "details" : {
            "type" : "Dog", 
            "weight" : 20,
            "awards" : { 
                "Florida Dog Awards" : "Top Dog", 
                "New York Marathon" : "Fastest Dog", 
                "Sumo 2020" : "Biggest Dog"
            }
        }
    }
';
SELECT JSON_EXTRACT(
    @json_document, 
    '$.details.awards.New York Marathon'
    ) AS Result;

Result:

+---------------+
| Result        |
+---------------+
| "Fastest Dog" |
+---------------+

However, if we wanted to extract all awards, we could shorten the path to $.details.awards:

SET @json_document = '
    { 
        "_id" : 1, 
        "name" : "Wag", 
        "details" : {
            "type" : "Dog", 
            "weight" : 20,
            "awards" : { 
                "Florida Dog Awards" : "Top Dog", 
                "New York Marathon" : "Fastest Dog", 
                "Sumo 2020" : "Biggest Dog"
            }
        }
    }
';
SELECT JSON_EXTRACT(
    @json_document, 
    '$.details.awards'
    ) AS Result;

Result:

+---------------------------------------------------------------------------------------------------+
| Result                                                                                            |
+---------------------------------------------------------------------------------------------------+
| {"Florida Dog Awards": "Top Dog", "New York Marathon": "Fastest Dog", "Sumo 2020": "Biggest Dog"} |
+---------------------------------------------------------------------------------------------------+

Prettify the Result

We can make the result easier to read by passing JSON_EXTRACT() to the JSON_DETAILED() function:

SET @json_document = '
    { 
        "_id" : 1, 
        "name" : "Wag", 
        "details" : {
            "type" : "Dog", 
            "weight" : 20,
            "awards" : { 
                "Florida Dog Awards" : "Top Dog", 
                "New York Marathon" : "Fastest Dog", 
                "Sumo 2020" : "Biggest Dog"
            }
        }
    }
';
SELECT 
    JSON_DETAILED(
        JSON_EXTRACT(
            @json_document, 
            '$.details.awards'
            ) 
    ) AS Result;

Result:

+------------------------------------------------+
| Result                                         |
+------------------------------------------------+
| {
    "Florida Dog Awards": "Top Dog",
    "New York Marathon": "Fastest Dog",
    "Sumo 2020": "Biggest Dog"
} |
+------------------------------------------------+

Null Arguments

If any argument is NULL, the result is NULL:

SELECT 
    JSON_EXTRACT(null, '$.type'),
    JSON_EXTRACT('{"a":1}', null);

Result:

+------------------------------+-------------------------------+
| JSON_EXTRACT(null, '$.type') | JSON_EXTRACT('{"a":1}', null) |
+------------------------------+-------------------------------+
| NULL                         | NULL                          |
+------------------------------+-------------------------------+

Incorrect Parameter Count

Providing no arguments results in an error:

SELECT JSON_EXTRACT();

Result:

ERROR 1582 (42000): Incorrect parameter count in the call to native function 'JSON_EXTRACT'

It’s the same when you provide too few or too many arguments:

SELECT JSON_EXTRACT('{ "a": 1}');

Result:

ERROR 1582 (42000): Incorrect parameter count in the call to native function 'JSON_EXTRACT'