JSON_QUOTE

La función JSON_QUOTE toma una cadena de texto SQL y la convierte en un valor JSON string válido, encerrándola entre comillas dobles y escapando los caracteres especiales según las reglas del estándar JSON. Es la operación inversa de JSON_UNQUOTE: mientras JSON_UNQUOTE extrae el texto plano de un string JSON, JSON_QUOTE envuelve texto plano para que sea un string JSON válido.

Sintaxis

JSON_QUOTE(cadena)

La función recibe una cadena de texto SQL y devuelve un valor JSON de tipo string. Esto significa que el resultado estará envuelto en comillas dobles y los siguientes caracteres se escaparán automáticamente:

Las comillas dobles (") se convierten en \". Las barras invertidas (\) se convierten en \\. Los saltos de línea (\n), retornos de carro (\r), tabulaciones (\t) y otros caracteres de control se escapan con sus secuencias correspondientes. Los caracteres nulos (\0) se convierten en \u0000.

Comportamiento básico

Veamos cómo JSON_QUOTE transforma cadenas simples:

SELECT JSON_QUOTE('Hola mundo') AS resultado;
resultado
"Hola mundo"

El resultado incluye las comillas dobles como parte del valor. Esto es un string JSON válido que puedes insertar directamente en un documento JSON.

Con caracteres especiales:

SELECT JSON_QUOTE('Precio: 29.99€ - Oferta "especial"') AS resultado;
resultado
"Precio: 29.99\u20ac - Oferta "especial""

Las comillas dobles internas se han escapado con barra invertida, y el carácter euro se ha convertido a su representación Unicode. Esto garantiza que el resultado siempre sea un JSON válido, independientemente del contenido de la cadena original.

Con saltos de línea y tabulaciones:

SELECT JSON_QUOTE('Línea 1\nLínea 2\tTabulado') AS resultado;
resultado
"Línea 1\nLínea 2\tTabulado"

Nota que en este caso los \n y \t del texto SQL ya eran literales de dos caracteres (barra y letra), así que JSON_QUOTE escapa la barra. Si la cadena contuviera un salto de línea real, se convertiría en la secuencia de escape JSON \n.

Caso práctico: construir JSON manualmente

Aunque MySQL ofrece funciones como JSON_OBJECT y JSON_ARRAY para construir documentos, a veces necesitas construir fragmentos JSON manualmente. JSON_QUOTE garantiza que los valores string sean válidos:

SELECT CONCAT(
    '{"producto": ',
    JSON_QUOTE('iPhone 15 Pro - Edición "Titanio"'),
    ', "precio": 1299.99}'
) AS json_manual;
json_manual
{"producto": "iPhone 15 Pro - Edición "Titanio"", "precio": 1299.99}

Sin JSON_QUOTE, las comillas dobles dentro del nombre del producto romperían la estructura JSON. La función se encarga de escaparlas correctamente.

Este patrón es útil cuando generas JSON en procedimientos almacenados o cuando necesitas interpolar valores dentro de plantillas JSON:

SET @nombre_producto = 'Camiseta "Premium" algodón 100%';
SET @descripcion = 'Camiseta de manga corta.\nDisponible en 5 colores.\nTalla: S-XXL.';
 
SELECT CONCAT(
    '{"nombre": ', JSON_QUOTE(@nombre_producto),
    ', "descripcion": ', JSON_QUOTE(@descripcion),
    '}'
) AS documento;

El resultado es un documento JSON válido donde todos los caracteres especiales están correctamente escapados.

Caso práctico: preparar valores para JSON_CONTAINS

La función JSON_CONTAINS requiere que sus argumentos sean valores JSON válidos. Cuando buscas una cadena dentro de un array JSON, necesitas pasarla como string JSON (con comillas dobles). JSON_QUOTE facilita esta tarea:

CREATE TABLE productos (
    id INT AUTO_INCREMENT PRIMARY KEY,
    nombre VARCHAR(200),
    etiquetas JSON
);
 
INSERT INTO productos (nombre, etiquetas) VALUES
('iPhone 15 Pro', '["smartphone", "apple", "5g"]'),
('MacBook Air M3', '["portátil", "apple", "ultrabook"]');
SET @buscar = 'apple';
 
SELECT nombre
FROM productos
WHERE JSON_CONTAINS(etiquetas, JSON_QUOTE(@buscar));
nombre
iPhone 15 Pro
MacBook Air M3

Sin JSON_QUOTE, tendrías que escribir '"apple"' manualmente (comillas simples rodeando comillas dobles rodeando el valor), lo cual es confuso y propenso a errores. JSON_QUOTE(@buscar) produce "apple" automáticamente, que es exactamente lo que JSON_CONTAINS necesita.

Caso práctico: almacenar texto con caracteres especiales

Cuando almacenas texto de usuario que puede contener cualquier carácter, JSON_QUOTE es útil para verificar cómo se representará en JSON:

SELECT
    JSON_QUOTE('Texto normal') AS normal,
    JSON_QUOTE('Ruta: C:\\Users\\datos') AS ruta_windows,
    JSON_QUOTE('{"clave": "valor"}') AS json_como_texto;
normalruta_windowsjson_como_texto
"Texto normal""Ruta: C:\\Users\\datos""{"clave": "valor"}"

La última columna es interesante: cuando almacenas JSON como texto dentro de otro JSON (JSON anidado como string), las comillas y barras se escapan para que el resultado siga siendo JSON válido. Esto se conoce como "doble escapado" y es habitual cuando se almacenan payloads de API que ya vienen en formato JSON.

Diferencia con CAST y JSON_OBJECT

Es importante entender cuándo usar JSON_QUOTE y cuándo otras alternativas:

SELECT
    JSON_QUOTE('42') AS quote_numero,
    CAST('42' AS JSON) AS cast_numero,
    JSON_QUOTE('true') AS quote_booleano,
    CAST('true' AS JSON) AS cast_booleano;
quote_numerocast_numeroquote_booleanocast_booleano
"42"42"true"true

JSON_QUOTE siempre produce un string JSON (entre comillas dobles). CAST(... AS JSON) interpreta el contenido: '42' se convierte en el número JSON 42, y 'true' en el booleano JSON true. Elige JSON_QUOTE cuando quieres forzar que el resultado sea un string, y CAST cuando quieres que MySQL interprete el tipo.

Cuando construyes objetos, JSON_OBJECT maneja las conversiones automáticamente:

SELECT JSON_OBJECT('nombre', 'iPhone 15 Pro', 'precio', 1299.99) AS resultado;
resultado
{"nombre": "iPhone 15 Pro", "precio": 1299.99}

JSON_OBJECT entrecomilla las cadenas y deja los números sin comillas. No necesitas JSON_QUOTE dentro de JSON_OBJECT.

Manejo de NULL

Si el argumento es NULL, JSON_QUOTE devuelve NULL (no la cadena "null"):

SELECT JSON_QUOTE(NULL) AS resultado;
resultado
NULL

Esto es diferente de la cadena JSON "null". Si necesitas el literal JSON null, usa CAST('null' AS JSON) en su lugar.

Con cadenas vacías, la función devuelve un string JSON vacío:

SELECT JSON_QUOTE('') AS resultado;
resultado
""

El resultado son dos comillas dobles, que representan un string JSON vacío.

Combinación con otras funciones

Puedes usar JSON_QUOTE en combinación con funciones de cadena para preparar valores dinámicamente:

SELECT JSON_QUOTE(
    CONCAT(nombre, ' - ', precio, '€')
) AS etiqueta_json
FROM productos;
etiqueta_json
"iPhone 15 Pro - 1299.99\u20ac"
"MacBook Air M3 - 1399.00\u20ac"

También es útil junto con JSON_ARRAY cuando necesitas garantizar que ciertos valores se traten como strings:

SELECT JSON_ARRAY(
    JSON_QUOTE('{"esto": "es texto, no un objeto"}'),
    JSON_OBJECT('esto', 'sí es un objeto')
) AS resultado;

En este caso, el primer elemento del array es un string que contiene texto con formato JSON, mientras que el segundo es un objeto JSON real. La diferencia es fundamental para aplicaciones que necesitan distinguir entre datos estructurados y texto plano.

En el siguiente artículo veremos JSON_UNQUOTE para el proceso inverso.

Escrito por Eduardo Lázaro