JSON_REMOVE
La función JSON_REMOVE elimina uno o varios valores de un documento JSON dadas sus rutas. Es la única forma de quitar completamente una clave de un objeto o un elemento de un array JSON. A diferencia de JSON_REPLACE con valor NULL (que establece la clave a null pero la mantiene), JSON_REMOVE borra la clave y su valor por completo del documento.
Sintaxis
JSON_REMOVE(documento_json, ruta [, ruta2, ruta3, ...])El primer argumento es el documento JSON original. Los argumentos restantes son una o más rutas JSON Path que indican qué valores eliminar. La función devuelve el documento modificado sin los elementos especificados. Si una ruta no existe en el documento, se ignora sin generar error.
Comportamiento básico
Eliminar una clave de un objeto JSON:
SELECT JSON_REMOVE(
'{"nombre": "Monitor 4K", "precio": 349.99, "stock": 45, "obsoleto": true}',
'$.obsoleto'
) AS resultado;| resultado |
|---|
| {"nombre": "Monitor 4K", "precio": 349.99, "stock": 45} |
La clave obsoleto y su valor desaparecieron completamente del documento. Compara esto con establecer el valor a null:
SELECT JSON_SET(
'{"nombre": "Monitor 4K", "obsoleto": true}',
'$.obsoleto', NULL
) AS con_set;| con_set |
|---|
| {"nombre": "Monitor 4K", "obsoleto": null} |
Con JSON_SET, la clave sigue existiendo con valor null. Con JSON_REMOVE, la clave desaparece por completo. La diferencia es importante cuando verificas la existencia de claves con JSON_CONTAINS_PATH.
Eliminar múltiples claves
Puedes eliminar varias claves en una sola llamada:
SELECT JSON_REMOVE(
'{"nombre": "iPhone 15", "precio": 1299, "stock": 50, "datos_internos": "xxx", "temp_id": 42}',
'$.datos_internos',
'$.temp_id'
) AS resultado;| resultado |
|---|
| {"nombre": "iPhone 15", "precio": 1299, "stock": 50} |
Las rutas se procesan de izquierda a derecha. Esto es relevante cuando eliminas elementos de arrays, como veremos más adelante.
Caso práctico: limpiar datos sensibles antes de enviar al frontend
Un caso de uso muy frecuente es eliminar información sensible o interna de un documento JSON antes de enviarlo al cliente:
CREATE TABLE usuarios (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(100) NOT NULL,
datos JSON
);
INSERT INTO usuarios (nombre, datos) VALUES
('Laura Martínez', '{
"email": "laura@example.com",
"telefono": "+34 612 345 678",
"direccion": {"calle": "Gran Vía 28", "ciudad": "Madrid", "cp": "28013"},
"hash_password": "$2b$12$abc123...",
"token_recuperacion": "tk_xyz789",
"intentos_login": 0,
"ip_ultimo_acceso": "192.168.1.50"
}');SELECT JSON_REMOVE(
datos,
'$.hash_password',
'$.token_recuperacion',
'$.intentos_login',
'$.ip_ultimo_acceso'
) AS datos_publicos
FROM usuarios
WHERE id = 1;| datos_publicos |
|---|
| {"email": "laura@example.com", "telefono": "+34 612 345 678", "direccion": {"calle": "Gran Vía 28", "ciudad": "Madrid", "cp": "28013"}} |
Los campos sensibles se eliminaron del documento. La información pública (email, teléfono, dirección) permanece intacta.
Caso práctico: eliminar elementos de arrays
Al eliminar un elemento de un array, es crucial entender que los índices se desplazan. Si eliminas el elemento en la posición 1, el que estaba en la posición 2 pasa a ser la posición 1:
SELECT JSON_REMOVE(
'{"colores": ["rojo", "azul", "verde", "amarillo"]}',
'$.colores[1]'
) AS resultado;| resultado |
|---|
| {"colores": ["rojo", "verde", "amarillo"]} |
Se eliminó "azul" (posición 1). Ahora "verde" ocupa la posición 1 y "amarillo" la posición 2. Este desplazamiento tiene implicaciones importantes cuando eliminas múltiples elementos del mismo array en una sola llamada:
-- Intentar eliminar "azul" (pos 1) y "amarillo" (pos 3)
SELECT JSON_REMOVE(
'{"colores": ["rojo", "azul", "verde", "amarillo"]}',
'$.colores[1]',
'$.colores[3]'
) AS resultado;| resultado |
|---|
| {"colores": ["rojo", "verde", "amarillo"]} |
Solo se eliminó "azul", no "amarillo". Esto ocurre porque las rutas se procesan en orden. Después de eliminar la posición 1, el array tiene 3 elementos (posiciones 0-2), así que la posición 3 ya no existe. Para eliminar ambos correctamente, debes empezar por los índices más altos:
-- Orden correcto: primero el índice mayor
SELECT JSON_REMOVE(
'{"colores": ["rojo", "azul", "verde", "amarillo"]}',
'$.colores[3]',
'$.colores[1]'
) AS resultado;| resultado |
|---|
| {"colores": ["rojo", "verde"]} |
Al eliminar primero la posición 3 ("amarillo"), el array queda con 3 elementos y la posición 1 sigue siendo "azul". Luego se elimina "azul" correctamente.
Caso práctico: limpiar datos de productos descatalogados
Antes de archivar productos, puedes querer eliminar información operativa manteniendo solo los datos esenciales:
CREATE TABLE productos (
id INT AUTO_INCREMENT PRIMARY KEY,
nombre VARCHAR(200) NOT NULL,
datos JSON
);
INSERT INTO productos (nombre, datos) VALUES
('Cargador USB-C 65W', '{
"marca": "Anker",
"precio": 35.99,
"stock": 0,
"proveedor": {"nombre": "Tech Import SL", "contacto": "proveedor@example.com", "contrato": "CT-2024-001"},
"ubicacion_almacen": "Estante B-14",
"ultima_reposicion": "2024-01-15",
"notas_internas": "Pendiente de descatalogación"
}');
-- Eliminar datos operativos del producto descatalogado
UPDATE productos
SET datos = JSON_REMOVE(
datos,
'$.stock',
'$.proveedor',
'$.ubicacion_almacen',
'$.ultima_reposicion',
'$.notas_internas'
)
WHERE id = 1;
SELECT datos
FROM productos
WHERE id = 1;| datos |
|---|
| {"marca": "Anker", "precio": 35.99} |
Solo quedaron la marca y el precio como referencia histórica. Toda la información operativa se eliminó del documento.
Eliminar claves de objetos anidados
JSON_REMOVE funciona con rutas de cualquier profundidad:
SELECT JSON_REMOVE(
'{"usuario": {"nombre": "Ana", "email": "ana@example.com", "temp_token": "abc123"}}',
'$.usuario.temp_token'
) AS resultado;| resultado |
|---|
| {"usuario": {"nombre": "Ana", "email": "ana@example.com"}} |
La clave temp_token se eliminó del objeto anidado usuario, pero el resto del objeto permaneció intacto.
Manejo de NULL
Cuando el documento JSON original es NULL, JSON_REMOVE devuelve NULL:
SELECT JSON_REMOVE(NULL, '$.clave') AS resultado;| resultado |
|---|
| NULL |
Cuando la ruta no existe en el documento, la operación se ignora sin error:
SELECT JSON_REMOVE(
'{"nombre": "Test"}',
'$.campo_inexistente'
) AS resultado;| resultado |
|---|
| {"nombre": "Test"} |
El documento permanece sin cambios. Este comportamiento silencioso hace que JSON_REMOVE sea seguro de usar incluso cuando no estás seguro de si la clave existe.
Combinación con otras funciones
JSON_REMOVE se combina frecuentemente con JSON_SET o JSON_INSERT en operaciones donde necesitas reestructurar un documento. Por ejemplo, renombrar una clave requiere copiar su valor a la nueva clave y eliminar la antigua:
-- "Renombrar" la clave "precio" a "precio_eur"
SET @doc = '{"nombre": "Monitor", "precio": 349.99}';
SELECT JSON_REMOVE(
JSON_SET(@doc, '$.precio_eur', JSON_EXTRACT(@doc, '$.precio')),
'$.precio'
) AS resultado;| resultado |
|---|
| {"nombre": "Monitor", "precio_eur": 349.99} |
Primero JSON_SET copia el valor de precio a una nueva clave precio_eur, y luego JSON_REMOVE elimina la clave original precio. El resultado es un documento donde la clave ha sido efectivamente renombrada.
En el siguiente artículo veremos JSON_KEYS para obtener las claves de un objeto JSON.
Escrito por Eduardo Lázaro
