MySQL :: MySQL 8.4 Reference Manual :: 14.17.8 JSON Utility Functions (original) (raw)

14.17.8 JSON Utility Functions

This section documents utility functions that act on JSON values, or strings that can be parsed as JSON values.JSON_PRETTY() prints out a JSON value in a format that is easy to read.JSON_STORAGE_SIZE() andJSON_STORAGE_FREE() show, respectively, the amount of storage space used by a given JSON value and the amount of space remaining in aJSON column following a partial update.

mysql> SELECT JSON_PRETTY('123'); # scalar  
+--------------------+  
| JSON_PRETTY('123') |  
+--------------------+  
| 123                |  
+--------------------+  
mysql> SELECT JSON_PRETTY("[1,3,5]"); # array  
+------------------------+  
| JSON_PRETTY("[1,3,5]") |  
+------------------------+  
| [  
  1,  
  3,  
  5  
]      |  
+------------------------+  
mysql> SELECT JSON_PRETTY('{"a":"10","b":"15","x":"25"}'); # object  
+---------------------------------------------+  
| JSON_PRETTY('{"a":"10","b":"15","x":"25"}') |  
+---------------------------------------------+  
| {  
  "a": "10",  
  "b": "15",  
  "x": "25"  
}   |  
+---------------------------------------------+  
mysql> SELECT JSON_PRETTY('["a",1,{"key1":  
    '>    "value1"},"5",     "77" ,  
    '>       {"key2":["value3","valueX",  
    '> "valueY"]},"j", "2"   ]')\G  # nested arrays and objects  
*************************** 1. row ***************************  
JSON_PRETTY('["a",1,{"key1":  
             "value1"},"5",     "77" ,  
                {"key2":["value3","valuex",  
          "valuey"]},"j", "2"   ]'): [  
  "a",  
  1,  
  {  
    "key1": "value1"  
  },  
  "5",  
  "77",  
  {  
    "key2": [  
      "value3",  
      "valuex",  
      "valuey"  
    ]  
  },  
  "j",  
  "2"  
]  
mysql> CREATE TABLE jtable (jcol JSON);  
Query OK, 0 rows affected (0.38 sec)  
mysql> INSERT INTO jtable VALUES  
    ->     ('{"a": 10, "b": "wxyz", "c": "[true, false]"}');  
Query OK, 1 row affected (0.04 sec)  
mysql> SELECT * FROM jtable;  
+----------------------------------------------+  
| jcol                                         |  
+----------------------------------------------+  
| {"a": 10, "b": "wxyz", "c": "[true, false]"} |  
+----------------------------------------------+  
1 row in set (0.00 sec)  

Now we update the column value usingJSON_SET() such that a partial update can be performed; in this case, we replace the value pointed to by the c key (the array [true, false]) with one that takes up less space (the integer 1):

mysql> UPDATE jtable  
    ->     SET jcol = JSON_SET(jcol, "$.a", 10, "$.b", "wxyz", "$.c", 1);  
Query OK, 1 row affected (0.03 sec)  
Rows matched: 1  Changed: 1  Warnings: 0  
mysql> SELECT * FROM jtable;  
+--------------------------------+  
| jcol                           |  
+--------------------------------+  
| {"a": 10, "b": "wxyz", "c": 1} |  
+--------------------------------+  
1 row in set (0.00 sec)  
mysql> SELECT JSON_STORAGE_FREE(jcol) FROM jtable;  
+-------------------------+  
| JSON_STORAGE_FREE(jcol) |  
+-------------------------+  
|                      14 |  
+-------------------------+  
1 row in set (0.00 sec)  

The effects of successive partial updates on this free space are cumulative, as shown in this example usingJSON_SET() to reduce the space taken up by the value having key b (and making no other changes):

mysql> UPDATE jtable  
    ->     SET jcol = JSON_SET(jcol, "$.a", 10, "$.b", "wx", "$.c", 1);  
Query OK, 1 row affected (0.03 sec)  
Rows matched: 1  Changed: 1  Warnings: 0  
mysql> SELECT JSON_STORAGE_FREE(jcol) FROM jtable;  
+-------------------------+  
| JSON_STORAGE_FREE(jcol) |  
+-------------------------+  
|                      16 |  
+-------------------------+  
1 row in set (0.00 sec)  

Updating the column without usingJSON_SET(),JSON_REPLACE(), orJSON_REMOVE() means that the optimizer cannot perform the update in place; in this case,JSON_STORAGE_FREE() returns 0, as shown here:

mysql> UPDATE jtable SET jcol = '{"a": 10, "b": 1}';  
Query OK, 1 row affected (0.05 sec)  
Rows matched: 1  Changed: 1  Warnings: 0  
mysql> SELECT JSON_STORAGE_FREE(jcol) FROM jtable;  
+-------------------------+  
| JSON_STORAGE_FREE(jcol) |  
+-------------------------+  
|                       0 |  
+-------------------------+  
1 row in set (0.00 sec)  

Partial updates of JSON documents can be performed only on column values. For a user variable that stores a JSON value, the value is always completely replaced, even when the update is performed using JSON_SET():

mysql> SET @j = '{"a": 10, "b": "wxyz", "c": "[true, false]"}';  
Query OK, 0 rows affected (0.00 sec)  
mysql> SET @j = JSON_SET(@j, '$.a', 10, '$.b', 'wxyz', '$.c', '1');  
Query OK, 0 rows affected (0.00 sec)  
mysql> SELECT @j, JSON_STORAGE_FREE(@j) AS Free;  
+----------------------------------+------+  
| @j                               | Free |  
+----------------------------------+------+  
| {"a": 10, "b": "wxyz", "c": "1"} |    0 |  
+----------------------------------+------+  
1 row in set (0.00 sec)  

For a JSON literal, this function always returns 0:

mysql> SELECT JSON_STORAGE_FREE('{"a": 10, "b": "wxyz", "c": "1"}') AS Free;  
+------+  
| Free |  
+------+  
|    0 |  
+------+  
1 row in set (0.00 sec)  
mysql> CREATE TABLE jtable (jcol JSON);  
Query OK, 0 rows affected (0.42 sec)  
mysql> INSERT INTO jtable VALUES  
    ->     ('{"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"}');  
Query OK, 1 row affected (0.04 sec)  
mysql> SELECT  
    ->     jcol,  
    ->     JSON_STORAGE_SIZE(jcol) AS Size,  
    ->     JSON_STORAGE_FREE(jcol) AS Free  
    -> FROM jtable;  
+-----------------------------------------------+------+------+  
| jcol                                          | Size | Free |  
+-----------------------------------------------+------+------+  
| {"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"} |   47 |    0 |  
+-----------------------------------------------+------+------+  
1 row in set (0.00 sec)  

According to the output ofJSON_STORAGE_SIZE(), the JSON document inserted into the column takes up 47 bytes. We also checked the amount of space freed by any previous partial updates of the column usingJSON_STORAGE_FREE(); since no updates have yet been performed, this is 0, as expected.
Next we perform an UPDATE on the table that should result in a partial update of the document stored in jcol, and then test the result as shown here:

mysql> UPDATE jtable SET jcol =  
    ->     JSON_SET(jcol, "$.b", "a");  
Query OK, 1 row affected (0.04 sec)  
Rows matched: 1  Changed: 1  Warnings: 0  
mysql> SELECT  
    ->     jcol,  
    ->     JSON_STORAGE_SIZE(jcol) AS Size,  
    ->     JSON_STORAGE_FREE(jcol) AS Free  
    -> FROM jtable;  
+--------------------------------------------+------+------+  
| jcol                                       | Size | Free |  
+--------------------------------------------+------+------+  
| {"a": 1000, "b": "a", "c": "[1, 3, 5, 7]"} |   47 |    3 |  
+--------------------------------------------+------+------+  
1 row in set (0.00 sec)  

The value returned by JSON_STORAGE_FREE() in the previous query indicates that a partial update of the JSON document was performed, and that this freed 3 bytes of space used to store it. The result returned byJSON_STORAGE_SIZE() is unchanged by the partial update.
Partial updates are supported for updates usingJSON_SET(),JSON_REPLACE(), orJSON_REMOVE(). The direct assignment of a value to a JSON column cannot be partially updated; following such an update,JSON_STORAGE_SIZE() always shows the storage used for the newly-set value:

mysql> UPDATE jtable  
mysql>     SET jcol = '{"a": 4.55, "b": "wxyz", "c": "[true, false]"}';  
Query OK, 1 row affected (0.04 sec)  
Rows matched: 1  Changed: 1  Warnings: 0  
mysql> SELECT  
    ->     jcol,  
    ->     JSON_STORAGE_SIZE(jcol) AS Size,  
    ->     JSON_STORAGE_FREE(jcol) AS Free  
    -> FROM jtable;  
+------------------------------------------------+------+------+  
| jcol                                           | Size | Free |  
+------------------------------------------------+------+------+  
| {"a": 4.55, "b": "wxyz", "c": "[true, false]"} |   56 |    0 |  
+------------------------------------------------+------+------+  
1 row in set (0.00 sec)  

A JSON user variable cannot be partially updated. This means that this function always shows the space currently used to store a JSON document in a user variable:

mysql> SET @j = '[100, "sakila", [1, 3, 5], 425.05]';  
Query OK, 0 rows affected (0.00 sec)  
mysql> SELECT @j, JSON_STORAGE_SIZE(@j) AS Size;  
+------------------------------------+------+  
| @j                                 | Size |  
+------------------------------------+------+  
| [100, "sakila", [1, 3, 5], 425.05] |   45 |  
+------------------------------------+------+  
1 row in set (0.00 sec)  
mysql> SET @j = JSON_SET(@j, '$[1]', "json");  
Query OK, 0 rows affected (0.00 sec)  
mysql> SELECT @j, JSON_STORAGE_SIZE(@j) AS Size;  
+----------------------------------+------+  
| @j                               | Size |  
+----------------------------------+------+  
| [100, "json", [1, 3, 5], 425.05] |   43 |  
+----------------------------------+------+  
1 row in set (0.00 sec)  
mysql> SET @j = JSON_SET(@j, '$[2][0]', JSON_ARRAY(10, 20, 30));  
Query OK, 0 rows affected (0.00 sec)  
mysql> SELECT @j, JSON_STORAGE_SIZE(@j) AS Size;  
+---------------------------------------------+------+  
| @j                                          | Size |  
+---------------------------------------------+------+  
| [100, "json", [[10, 20, 30], 3, 5], 425.05] |   56 |  
+---------------------------------------------+------+  
1 row in set (0.00 sec)  

For a JSON literal, this function always returns the current storage space used:

mysql> SELECT  
    ->     JSON_STORAGE_SIZE('[100, "sakila", [1, 3, 5], 425.05]') AS A,  
    ->     JSON_STORAGE_SIZE('{"a": 1000, "b": "a", "c": "[1, 3, 5, 7]"}') AS B,  
    ->     JSON_STORAGE_SIZE('{"a": 1000, "b": "wxyz", "c": "[1, 3, 5, 7]"}') AS C,  
    ->     JSON_STORAGE_SIZE('[100, "json", [[10, 20, 30], 3, 5], 425.05]') AS D;  
+----+----+----+----+  
| A  | B  | C  | D  |  
+----+----+----+----+  
| 45 | 44 | 47 | 56 |  
+----+----+----+----+  
1 row in set (0.00 sec)