MariaDB JSON_OBJECTAGG() Explained

In MariaDB, JSON_OBJECTAGG() is a built-in function that returns a JSON object containing key-value pairs, based on its two arguments.

Syntax

The syntax goes like this:

JSON_OBJECTAGG(key, value)

The function accepts two expressions that evaluate to a single value, or two column names, as arguments. The first argument is the key, and the second is its value.

Example

Here’s a simple example to demonstrate:

SELECT JSON_OBJECTAGG("name", "Homer");

Result:

+---------------------------------+
| JSON_OBJECTAGG("name", "Homer") |
+---------------------------------+
| {"name":"Homer"}                |
+---------------------------------+

Although this example demonstrates how the function works, the real benefit comes in when working with columns or other expressions.

Below are examples that use database columns for the arguments.

A Database Example

Suppose we query a table:

SELECT 
    PetName,
    DOB
FROM Pets;

And get the following result set:

+---------+------------+
| PetName | DOB        |
+---------+------------+
| Fluffy  | 2020-11-20 |
| Fetch   | 2019-08-16 |
| Scratch | 2018-10-01 |
| Wag     | 2020-03-15 |
| Tweet   | 2020-11-28 |
| Fluffy  | 2020-09-17 |
| Bark    | NULL       |
| Meow    | NULL       |
+---------+------------+

Let’s now run a query that passes each column to the JSON_OBJECTAGG() function, so that the results are returned as a JSON object:

SELECT JSON_OBJECTAGG(PetName, DOB)
FROM Pets
WHERE DOB < '2020-04-01';

Result:

+--------------------------------------------------------------------+
| JSON_OBJECTAGG(PetName, DOB)                                       |
+--------------------------------------------------------------------+
| {"Fetch":"2019-08-16", "Scratch":"2018-10-01", "Wag":"2020-03-15"} |
+--------------------------------------------------------------------+

All we did was pass the column names to the JSON_OBJECTAGG() function.

We also used a WHERE clause to narrow the results down a bit.

Grouped Results

We can use the SQL GROUP BY clause to produce JSON objects based on a grouping of another column.

Suppose we add a column to our original query:

SELECT 
    PetTypeId,
    PetName,
    DOB
FROM Pets;

Result:

+-----------+---------+------------+
| PetTypeId | PetName | DOB        |
+-----------+---------+------------+
|         2 | Fluffy  | 2020-11-20 |
|         3 | Fetch   | 2019-08-16 |
|         2 | Scratch | 2018-10-01 |
|         3 | Wag     | 2020-03-15 |
|         1 | Tweet   | 2020-11-28 |
|         3 | Fluffy  | 2020-09-17 |
|         3 | Bark    | NULL       |
|         2 | Meow    | NULL       |
+-----------+---------+------------+

Now we have a PetTypeId column as well as the PetName and DOB columns. This matches a pet type to each pet.

Here’s an example of using the GROUP BY clause to group our results by the PetTypeId column while using the JSON_OBJECTAGG() function:

SELECT 
    PetTypeId,
    JSON_OBJECTAGG(PetName, DOB)
FROM Pets
GROUP BY PetTypeId;

Result:

+-----------+--------------------------------------------------------------------------------+
| PetTypeId | JSON_OBJECTAGG(PetName, DOB)                                                   |
+-----------+--------------------------------------------------------------------------------+
|         1 | {"Tweet":"2020-11-28"}                                                         |
|         2 | {"Fluffy":"2020-11-20", "Scratch":"2018-10-01", "Meow":null}                   |
|         3 | {"Fetch":"2019-08-16", "Wag":"2020-03-15", "Fluffy":"2020-09-17", "Bark":null} |
+-----------+--------------------------------------------------------------------------------+

This allowed us to create a separate JSON object for each pet type.

The following query uses an INNER JOIN on another table to return the actual pet type, not just the ID.

SELECT 
    pt.PetType,
    p.PetName,
    p.DOB
FROM Pets p 
INNER JOIN PetTypes pt 
ON pt.PetTypeId = p.PetTypeId
ORDER BY PetType;

Result:

+---------+---------+------------+
| PetType | PetName | DOB        |
+---------+---------+------------+
| Bird    | Tweet   | 2020-11-28 |
| Cat     | Scratch | 2018-10-01 |
| Cat     | Fluffy  | 2020-11-20 |
| Cat     | Meow    | NULL       |
| Dog     | Wag     | 2020-03-15 |
| Dog     | Fetch   | 2019-08-16 |
| Dog     | Bark    | NULL       |
| Dog     | Fluffy  | 2020-09-17 |
+---------+---------+------------+

We can see that the actual pet type is now listed in the first column, instead of just the pet type ID.

Now let’s use the JSON_OBJECTAGG() function:

SELECT 
    pt.PetType,
    JSON_OBJECTAGG(p.PetName, p.DOB)
FROM Pets p 
INNER JOIN PetTypes pt 
ON pt.PetTypeId = p.PetTypeId
GROUP BY pt.PetType;

Result:

+---------+--------------------------------------------------------------------------------+
| PetType | JSON_OBJECTAGG(p.PetName, p.DOB)                                               |
+---------+--------------------------------------------------------------------------------+
| Bird    | {"Tweet":"2020-11-28"}                                                         |
| Cat     | {"Scratch":"2018-10-01", "Fluffy":"2020-11-20", "Meow":null}                   |
| Dog     | {"Wag":"2020-03-15", "Fetch":"2019-08-16", "Bark":null, "Fluffy":"2020-09-17"} |
+---------+--------------------------------------------------------------------------------+