En MariaDB, JSON_TABLE()
es una función integrada que convierte datos JSON en un formato relacional.
En otras palabras, te permite devolver un documento JSON como una tabla.
El JSON_TABLE()
La función se introdujo en MariaDB 10.6.0.
Sintaxis
La sintaxis es así:
JSON_TABLE(json_doc,
context_path COLUMNS (column_list)
) [AS] alias
Donde column_list
va así:
column[, column][, ...]
Donde column
va así:
name FOR ORDINALITY
| name type PATH value_path path [on_empty] [on_error]
| name type EXISTS PATH value_path
| NESTED [PATH] path COLUMNS (column_list)
Donde on_empty
va así:
{NULL | DEFAULT string | ERROR} ON EMPTY
Y on_error
va así:
{NULL | DEFAULT string | ERROR} ON ERROR
Ejemplo
Aquí hay un ejemplo para demostrarlo.
SET @json_document = '
[
{ "name": "Wag", "type": "Dog", "weight": 20 },
{ "name": "Bark", "type": "Dog", "weight": 10 },
{ "name": "Meow", "type": "Cat", "weight": 7 }
]
';
SELECT * FROM JSON_TABLE(@json_document, '$[*]'
COLUMNS (
name VARCHAR(255) PATH '$.name',
type VARCHAR(50) PATH '$.type',
weight INT PATH '$.weight'
)
) AS json_table;
Resultado:
+------+------+--------+ | name | type | weight | +------+------+--------+ | Wag | Dog | 20 | | Bark | Dog | 10 | | Meow | Cat | 7 | +------+------+--------+
Aquí, nombramos cada columna de la tabla, especificamos su tipo de datos y luego especificamos la ruta del documento JSON que se aplicará a esa columna.
Entonces, llamamos a nuestra primera columna name
y luego asignó el nodo llamado name
del documento JSON a esa columna.
Columnas de ordinalidad
El FOR ORDINALITY
La opción se puede usar para contar las filas, comenzando desde 1
.
SET @json_document = '
[
{ "name": "Scratch", "type": "Cat", "weight": 8 },
{ "name": "Bruce", "type": "Kangaroo", "weight": 100 },
{ "name": "Hop", "type": "Kangaroo", "weight": 130 }
]
';
SELECT * FROM JSON_TABLE(@json_document, '$[*]'
COLUMNS (
id FOR ORDINALITY,
name VARCHAR(255) PATH '$.name',
type VARCHAR(50) PATH '$.type',
weight INT PATH '$.weight'
)
) AS json_table;
Resultado:
+------+---------+----------+--------+ | id | name | type | weight | +------+---------+----------+--------+ | 1 | Scratch | Cat | 8 | | 2 | Bruce | Kangaroo | 100 | | 3 | Hop | Kangaroo | 130 | +------+---------+----------+--------+
Comprobación de la existencia de una ruta
Puedes usar el EXISTS
cláusula para verificar la existencia de una ruta. Si la ruta existe en el documento JSON, el resultado es 1
. Si no existe, 0
es devuelto.
SET @json_document = '
[
{ "name": "Punch", "type": "Kangaroo", "weight": 200 },
{ "name": "Snap", "type": "Cat", "weight": 12 },
{ "name": "Ruff", "type": "Dog" }
]
';
SELECT * FROM JSON_TABLE(@json_document, '$[*]'
COLUMNS (
name VARCHAR(255) PATH '$.name',
type VARCHAR(50) PATH '$.type',
has_weight INT EXISTS PATH '$.weight'
)
) AS json_table;
Resultado:
+-------+----------+------------+ | name | type | has_weight | +-------+----------+------------+ | Punch | Kangaroo | 1 | | Snap | Cat | 1 | | Ruff | Dog | 0 | +-------+----------+------------+
Rutas anidadas
La NESTED PATH
cláusula le permite tratar con documentos JSON anidados. Cuando usa esta cláusula, convierte estructuras JSON anidadas en varias filas.
Ejemplo:
SET @json_document = '
[
{ "product": "Left Handed Screwdriver", "sizes": [ "S", "M", "L" ] },
{ "product": "Long Weight", "sizes": [ "S", "L", "XL" ] },
{ "product": "Bottomless Coffee Cup" }
]
';
SELECT * FROM JSON_TABLE(@json_document, '$[*]'
COLUMNS (
product VARCHAR(255) PATH '$.product',
NESTED PATH '$.sizes[*]' columns (
size VARCHAR(2) PATH '$'
)
)
) AS json_table;
Resultado:
+-------------------------+------+ | product | size | +-------------------------+------+ | Left Handed Screwdriver | S | | Left Handed Screwdriver | M | | Left Handed Screwdriver | L | | Long Weight | S | | Long Weight | L | | Long Weight | XL | | Bottomless Coffee Cup | NULL | +-------------------------+------+
Lidiando con caminos vacíos
El ON EMPTY
La cláusula especifica lo que se hará cuando el elemento especificado por la ruta de búsqueda falte en el documento JSON.
Ejemplo:
SET @json_document = '
[
{ "name": "Punch", "type": "Kangaroo", "weight": 200 },
{ "name": "Snap", "type": "Cat", "weight": 12 },
{ "name": "Ruff"}
]
';
SELECT * FROM JSON_TABLE(@json_document, '$[*]'
COLUMNS (
name VARCHAR(255) PATH '$.name',
type VARCHAR(50) PATH '$.type' DEFAULT "N/A" ON EMPTY,
weight INT PATH '$.weight'
)
) AS json_table;
Resultado:
+-------+----------+--------+ | name | type | weight | +-------+----------+--------+ | Punch | Kangaroo | 200 | | Snap | Cat | 12 | | Ruff | N/A | NULL | +-------+----------+--------+
En este ejemplo, Ruff
no tiene un campo de tipo y, por lo tanto, N/A
es regresado. Esto se debe a que lo especifiqué en ON EMPTY
cláusula para ese campo.
Lidiar con los errores
El ON ERROR
La cláusula especifica qué se debe hacer si se produce un error de estructura JSON al intentar extraer el valor del documento.
Un error de estructura JSON ocurre solo cuando intenta convertir un JSON no escalar (matriz u objeto) en un valor escalar. Cuando ON ERROR
la cláusula no está presente, NULL ON ERROR
está implícito.
Aquí hay un ejemplo de cómo manejar un error de estructura JSON:
SET @json_document = '
[
{ "product": "Left Handed Screwdriver", "sizes": [ "S", "M", "L" ] },
{ "product": "Long Weight", "sizes": [ "S", "L", "XL" ] },
{ "product": "Bottomless Coffee Cup" }
]
';
SELECT * FROM JSON_TABLE(@json_document, '$[*]'
COLUMNS (
product VARCHAR(255) PATH '$.product',
sizes VARCHAR(5) PATH '$.sizes'
DEFAULT 'Oops!' ON ERROR
DEFAULT 'None' ON EMPTY
)
) AS json_table;
Resultado:
+-------------------------+-------+ | product | sizes | +-------------------------+-------+ | Left Handed Screwdriver | Oops! | | Long Weight | Oops! | | Bottomless Coffee Cup | None | +-------------------------+-------+
Aquí, especifiqué una cadena (Oops!
) para usar cada vez que se produzca un error de estructura JSON.
En este caso, también incluí el ON EMPTY
cláusula. Esto demuestra que tanto el ON ERROR
y el ON EMPTY
cláusula se puede utilizar en la misma declaración.
Sin embargo, es importante tener en cuenta que un error de conversión de tipo de datos (por ejemplo, un intento de almacenar un valor no entero en un campo de enteros, o una columna varchar que se trunca) no se considera un error JSON y, por lo tanto, no activará el ON ERROR
cláusula. En su lugar, generará advertencias.
He aquí un ejemplo para ilustrar lo que quiero decir:
SET @json_document = '
[
{ "name": "Punch", "type": "Kangaroo" },
{ "name": "Snap", "type": "Cat" },
{ "name": "Ruff", "type": "Dog" }
]
';
SELECT * FROM JSON_TABLE(@json_document, '$[*]'
COLUMNS (
name VARCHAR(255) PATH '$.name',
type INT PATH '$.type' DEFAULT 'Oops!' ON ERROR
)
) AS json_table;
Resultado:
+-------+------+ | name | type | +-------+------+ | Punch | 0 | | Snap | 0 | | Ruff | 0 | +-------+------+ 3 rows in set, 3 warnings (0.000 sec)
Mostremos las advertencias:
SHOW WARNINGS;
Resultado:
+---------+------+---------------------------------------------------------------------------------+ | Level | Code | Message | +---------+------+---------------------------------------------------------------------------------+ | Warning | 1366 | Incorrect integer value: 'Kangaroo' for column ``.`(temporary)`.`type` at row 1 | | Warning | 1366 | Incorrect integer value: 'Cat' for column ``.`(temporary)`.`type` at row 2 | | Warning | 1366 | Incorrect integer value: 'Dog' for column ``.`(temporary)`.`type` at row 3 | +---------+------+---------------------------------------------------------------------------------+