JSON_ARRAY_APPEND
La función JSON_ARRAY_APPEND añade un valor al final de un array que se encuentra dentro de un documento JSON. Es la forma más directa de agregar elementos a arrays existentes sin necesidad de reemplazar todo el documento. Esto la convierte en una herramienta esencial cuando trabajas con listas de etiquetas, historiales de eventos, colecciones de imágenes, o cualquier estructura donde necesites acumular valores progresivamente.
Sintaxis
JSON_ARRAY_APPEND(json_doc, ruta, valor [, ruta, valor ...])La función recibe el documento JSON original, seguido de uno o más pares de ruta y valor. Cada par indica dónde añadir el nuevo elemento (la ruta al array) y qué valor añadir. Si la ruta apunta a un valor escalar en lugar de a un array, la función convierte ese escalar en un array de un elemento y luego añade el nuevo valor. Si la ruta apunta a un objeto, el valor se envuelve como un array y se añade. La función devuelve el documento JSON modificado.
JSON_ARRAY_APPEND(json_doc, '$.ruta', valor)
JSON_ARRAY_APPEND(json_doc, '$.ruta1', valor1, '$.ruta2', valor2)Comportamiento básico
Empecemos con el caso más simple: añadir un elemento al final de un array raíz:
SELECT JSON_ARRAY_APPEND(
'["rojo", "azul", "verde"]',
'$', 'amarillo'
) AS resultado;| resultado |
|---|
| ["rojo", "azul", "verde", "amarillo"] |
La ruta '$' hace referencia al documento raíz, que en este caso es el propio array. El valor 'amarillo' se añadió al final.
Para añadir a un array que está dentro de un objeto, usas la ruta correspondiente:
SELECT JSON_ARRAY_APPEND(
'{"nombre": "iPhone", "colores": ["negro", "blanco"]}',
'$.colores', 'titanio'
) AS resultado;| resultado |
|---|
| {"colores": ["negro", "blanco", "titanio"], "nombre": "iPhone"} |
El valor "titanio" se añadió al final del array colores. El resto del documento permaneció intacto.
Puedes añadir valores de cualquier tipo JSON, no solo cadenas:
SELECT JSON_ARRAY_APPEND(
'{"precios": [10.99, 24.50]}',
'$.precios', 15.75
) AS resultado;| resultado |
|---|
| {"precios": [10.99, 24.50, 15.75]} |
También puedes añadir a múltiples arrays en una sola llamada:
SELECT JSON_ARRAY_APPEND(
'{"tags": ["premium"], "colores": ["negro"]}',
'$.tags', '5g',
'$.colores', 'blanco'
) AS resultado;| resultado |
|---|
| {"colores": ["negro", "blanco"], "tags": ["premium", "5g"]} |
Un comportamiento especial ocurre cuando la ruta apunta a un valor escalar en lugar de un array. La función convierte automáticamente ese escalar en un array y luego añade el nuevo valor:
SELECT JSON_ARRAY_APPEND(
'{"color": "negro"}',
'$.color', 'blanco'
) AS resultado;| resultado |
|---|
| {"color": ["negro", "blanco"]} |
El valor escalar "negro" se convirtió en ["negro"] y luego se añadió "blanco".
Caso práctico: gestión de etiquetas de producto
Imagina una tienda en línea donde los administradores pueden añadir etiquetas a los productos de forma progresiva:
CREATE TABLE productos (
id INT PRIMARY KEY AUTO_INCREMENT,
nombre VARCHAR(100),
datos JSON
);
INSERT INTO productos (nombre, datos) VALUES
('iPhone 15 Pro', '{"precio": 1299, "etiquetas": ["smartphone", "apple"], "imágenes": ["frontal.jpg"]}'),
('Samsung Galaxy S24', '{"precio": 899, "etiquetas": ["smartphone"], "imágenes": ["frontal.jpg", "trasera.jpg"]}'),
('MacBook Air M3', '{"precio": 1399, "etiquetas": ["portátil", "apple"], "imágenes": []}');Para añadir la etiqueta "premium" al iPhone:
UPDATE productos
SET datos = JSON_ARRAY_APPEND(datos, '$.etiquetas', 'premium')
WHERE nombre = 'iPhone 15 Pro';Para añadir tanto una nueva etiqueta como una nueva imagen al Samsung:
UPDATE productos
SET datos = JSON_ARRAY_APPEND(
datos,
'$.etiquetas', '5g',
'$.imágenes', 'lateral.jpg'
)
WHERE nombre = 'Samsung Galaxy S24';Después de las actualizaciones:
SELECT
nombre,
datos->>'$.etiquetas' AS etiquetas,
datos->>'$.imágenes' AS imágenes
FROM productos;| nombre | etiquetas | imágenes |
|---|---|---|
| iPhone 15 Pro | ["smartphone", "apple", "premium"] | ["frontal.jpg"] |
| Samsung Galaxy S24 | ["smartphone", "5g"] | ["frontal.jpg", "trasera.jpg", "lateral.jpg"] |
| MacBook Air M3 | ["portátil", "apple"] | [] |
Caso práctico: registro de actividad del usuario
Un patrón habitual es mantener un log de actividades recientes de cada usuario como un array JSON:
CREATE TABLE sesiones (
id INT PRIMARY KEY AUTO_INCREMENT,
usuario VARCHAR(100),
actividad JSON
);
INSERT INTO sesiones (usuario, actividad) VALUES
('María García', '{"acciones": ["login"], "páginas": ["/inicio"]}'),
('Carlos López', '{"acciones": ["login"], "páginas": ["/inicio"]}');Cada vez que María realiza una acción, se añade al registro:
UPDATE sesiones
SET actividad = JSON_ARRAY_APPEND(
actividad,
'$.acciones', 'ver_producto',
'$.páginas', '/productos/iphone-15'
)
WHERE usuario = 'María García';
UPDATE sesiones
SET actividad = JSON_ARRAY_APPEND(
actividad,
'$.acciones', 'añadir_carrito',
'$.páginas', '/carrito'
)
WHERE usuario = 'María García';SELECT usuario, JSON_PRETTY(actividad) AS actividad
FROM sesiones
WHERE usuario = 'María García';| usuario | actividad |
|---|---|
| María García | {"acciones": ["login", "ver_producto", "añadir_carrito"], "páginas": ["/inicio", "/productos/iphone-15", "/carrito"]} |
Las acciones y las páginas se van acumulando cronológicamente sin perder las anteriores.
Caso práctico: añadir a arrays anidados
JSON_ARRAY_APPEND también funciona con arrays que están profundamente anidados dentro del documento:
SELECT JSON_ARRAY_APPEND(
'{"producto": {"specs": {"colores_disponibles": ["negro", "blanco"]}}}',
'$.producto.specs.colores_disponibles', 'azul'
) AS resultado;| resultado |
|---|
| {"producto": {"specs": {"colores_disponibles": ["negro", "blanco", "azul"]}}} |
Incluso puedes añadir a un elemento específico de un array de arrays:
SELECT JSON_ARRAY_APPEND(
'{"matriz": [[1, 2], [3, 4], [5, 6]]}',
'$.matriz[0]', 3
) AS resultado;| resultado |
|---|
| {"matriz": [[1, 2, 3], [3, 4], [5, 6]]} |
El valor 3 se añadió al primer sub-array (índice 0), dejando los demás intactos.
Manejo de NULL
Cuando el documento JSON es NULL, la función devuelve NULL:
SELECT JSON_ARRAY_APPEND(NULL, '$', 'valor') AS resultado;| resultado |
|---|
| NULL |
Si la ruta no existe en el documento, el valor no se añade y el documento se devuelve sin cambios:
SELECT JSON_ARRAY_APPEND(
'{"nombre": "iPhone"}',
'$.etiquetas', 'premium'
) AS resultado;| resultado |
|---|
| {"nombre": "iPhone"} |
Como la ruta $.etiquetas no existe, no hay ningún array al que añadir. Si necesitas crear el array cuando no existe, debes usar JSON_SET primero para crear un array vacío.
Combinación con otras funciones
Un patrón común es verificar la longitud del array antes de añadir, para imponer un límite máximo:
SELECT
nombre,
CASE
WHEN JSON_LENGTH(datos, '$.etiquetas') < 5
THEN JSON_ARRAY_APPEND(datos, '$.etiquetas', 'nueva_etiqueta')
ELSE datos
END AS datos_actualizados
FROM productos;También puedes combinar JSON_ARRAY_APPEND con JSON_CONTAINS para evitar duplicados antes de añadir:
UPDATE productos
SET datos = JSON_ARRAY_APPEND(datos, '$.etiquetas', '5g')
WHERE nombre = 'iPhone 15 Pro'
AND NOT JSON_CONTAINS(datos->'$.etiquetas', '"5g"');Esta consulta solo añade la etiqueta "5g" si no existe previamente en el array, evitando duplicados. Es un patrón que simula el comportamiento de un conjunto (set) sobre un array JSON. En el siguiente artículo veremos JSON_ARRAY_INSERT para insertar elementos en posiciones específicas.
Escrito por Eduardo Lázaro
