← Todos los artículos

Carácter mal escapado en JSON: causas, ejemplos y arreglos

Arregla errores "bad escaped character in JSON" por escapes \x, rutas de Windows, regex, valores \u malformados y JSON doblemente codificado.

SyntaxError: Bad escaped character in JSON at position N significa que el parser encontró una barra invertida (\) dentro de una cadena JSON y que el siguiente carácter no era uno de los caracteres de escape que JSON permite. Según la sección 7 del RFC 8259, las cadenas JSON pueden escapar comillas dobles, barra invertida, barra normal, los escapes de control b, f, n, r, t, o un escape Unicode escrito como u seguido de exactamente cuatro dígitos hexadecimales.

En depuración real, este error suele venir de un valor copiado: una ruta de Windows (C:\Users\Ada), un escape de JavaScript o del shell (\x1b), un patrón de regex (\d+), un escape Unicode de Python (\U0001F600) o una cadena que fue parcialmente desescapada desde un log. El arreglo no es "borrar barras invertidas". El arreglo es decidir cuál debe ser el valor final de la cadena y luego escribir el texto JSON que representa ese valor.

Esta guía se centra en la redacción de JSON.parse() de JavaScript, pero la misma regla se aplica a json.loads() de Python, encoding/json de Go, JSON.parse de Ruby, json_decode de PHP, jq, jsonb de Postgres y la mayoría de parsers JSON estrictos.

¿Qué error de cadena es este?

El arreglo en 30 segundos

  1. Ve a la position, line o column reportada.
  2. Mira el carácter inmediatamente anterior por si hay una barra invertida.
  3. Comprueba el carácter que va después de la barra invertida.
  4. Si la barra invertida es parte de los datos, escríbela como \\.
  5. Si el escape pertenece a otro lenguaje (\x, \d, \U), tradúcelo a la sintaxis de JSON.
  6. Si la barra invertida solo se copió de una línea de log entrecomillada, parsea una capa en vez de eliminarla con regex.

Ejemplo:

{"path":"C:\Users\Ada\file.json"}
           ^
           U is not valid after a JSON backslash

Texto JSON correcto:

{
  "path": "C:\\Users\\Ada\\file.json"
}

Tras el parseo, el valor real en la aplicación sigue siendo:

C:\Users\Ada\file.json

Las barras invertidas duplicadas solo existen en el texto JSON.

Cómo se ve el error

Diferentes motores usan una redacción ligeramente distinta:

// V8: Chrome, Node.js, Edge
SyntaxError: Bad escaped character in JSON at position 12

// Firefox
SyntaxError: JSON.parse: bad escaped character at line 1 column 13 of the JSON data

// Safari
SyntaxError: JSON Parse error: Invalid escape character \x

La position de V8 suele apuntar al carácter que va después de la barra invertida, no a la propia barra invertida. En este JSON roto, el carácter reportado es la U de \Users:

{"path":"C:\Users\Ada\file.json"}
           ^^
           \U is the bad escape

Así que cuando el mensaje dice position 12, inspecciona una ventana pequeña antes y después de la posición 12. El carácter incorrecto es útil, pero la barra invertida que lo precede es la que explica el error.

Los únicos escapes que JSON admite

Dentro de una cadena JSON, una barra invertida solo puede introducir estos escapes:

Escape JSON Carácter parseado Notas
\" " Obligatorio para una comilla doble dentro de una cadena JSON
\\ \ Obligatorio para una barra invertida literal
\/ / Opcional; / también es válido sin escapar
\b Backspace U+0008
\f Form feed U+000C; por eso \file es peligroso en rutas de Windows
\n Salto de línea U+000A
\r Retorno de carro U+000D
\t Tabulador U+0009
\uXXXX Unidad de código Unicode Exactamente cuatro dígitos hex después de la u minúscula

Todo lo demás es JSON inválido: \x, \', \d, \s, \w, \0, \v, \e, \U, \u{1F600}, \N{...}, \cA y escapes Unicode cortos como \u12.

Tabla de arreglos rápidos

Usa esta tabla cuando ya sepas cuál debe ser el valor final.

Texto JSON roto Por qué falla Texto JSON válido
{ "path": "C:\Users\Ada\file.json" } \U y \A son inválidos; \f es válido pero se convierte en form feed, no en separador de ruta. { "path": "C:\\Users\\Ada\\file.json" }
{ "path": "C:/Users/Ada/file.json" } Esto no falla. Las barras normales no necesitan escaparse. Consérvalo si el consumidor acepta barras normales.
{ "color": "\x1b[32mOK\x1b[0m" } JSON no tiene el escape \xNN. { "color": "\u001b[32mOK\u001b[0m" }
{ "name": "O\'Brien" } Los apóstrofos no necesitan escaparse dentro de cadenas JSON. { "name": "O'Brien" }
{ "pattern": "^\d{4}-\d{2}-\d{2}$" } \d es un escape de regex, no de JSON. { "pattern": "^\\d{4}-\\d{2}-\\d{2}$" }
{ "char": "\u12" } \u debe ir seguido de exactamente 4 dígitos hex. { "char": "\u0012" }
{ "emoji": "\u{1F600}" } JavaScript lo admite en cadenas de código fuente; JSON no. { "emoji": "😀" } o { "emoji": "\uD83D\uDE00" }

Un detalle incómodo merece su propia advertencia: \f es un escape JSON válido. Si una ruta de Windows contiene \file, un parser puede convertir eso en un carácter form feed seguido de ile. El parseo puede tener éxito mientras el valor de la ruta queda corrupto. Por eso "reparar" ciegamente cadenas de ruta es arriesgado.

Causa 1: rutas de Windows copiadas en JSON

Las rutas de Windows parecen inofensivas porque las personas leen la barra invertida como separador de ruta:

{ "downloadDir": "C:\Users\Ada\Downloads" }

JSON lee la barra invertida como el comienzo de una secuencia de escape. Ve \U y se detiene porque la U mayúscula no es un escape JSON.

Escribe barras invertidas dobles en JSON:

{
  "downloadDir": "C:\\Users\\Ada\\Downloads"
}

O usa barras normales si el programa receptor las acepta:

{
  "downloadDir": "C:/Users/Ada/Downloads"
}

Para ficheros de configuración, las barras normales suelen producir menos errores. Para valores exactos solo de Windows, las barras invertidas dobles son la representación JSON portable.

Causa 2: mezclar cadenas de código JavaScript con texto JSON

Aquí es donde muchos ejemplos en la web confunden a la gente sin querer. Hay dos capas:

  • La sintaxis de las cadenas de código fuente en JavaScript
  • La sintaxis del texto JSON dentro de esa cadena de JavaScript

Este código fuente de JavaScript es válido:

const raw = '{"path":"C:\\Users\\Ada"}';
JSON.parse(raw);

Pero el texto JSON que llega al parser es:

{"path":"C:\\Users\\Ada"}

Si quieres probar una muestra de JSON roto en JavaScript sin que el propio JavaScript consuma las barras invertidas primero, usa String.raw:

const broken = String.raw`{"path":"C:\Users\Ada"}`;
JSON.parse(broken);

Eso lanza Bad escaped character porque JSON.parse() recibe el texto JSON realmente roto.

Usa este modelo mental al leer stack traces: si el JSON vino de un fichero .json, un cuerpo HTTP, un valor de localStorage o una cadena de base de datos, arregla el texto JSON. Si el JSON está dentro de una cadena de código fuente JavaScript, puede que necesites un nivel de escape para JavaScript y otro nivel para JSON.

Causa 3: tomar prestados escapes de otros lenguajes

JSON acepta \n y \t, pero no acepta muchos escapes que son normales en lenguajes de programación:

{ "code": "\x1b[0m", "name": "O\'Brien" }

JSON válido:

{
  "code": "\u001b[0m",
  "name": "O'Brien"
}

Falsos amigos habituales:

Escape Válido en Arreglo en JSON
\x1b JavaScript, Python, muchos shells \u001b
\' Cadenas de comilla simple en JavaScript/Python Usa ' sin barra invertida
\0 Atajo NUL en JavaScript/Python \u0000
\v Tabulador vertical en JavaScript \u000b
\U0001F600 Escape Unicode de Python Emoji UTF-8 literal o par subrogado
\u{1F600} Escape de punto de código Unicode de JavaScript Emoji UTF-8 literal o par subrogado

Si el productor es tu propio código, no traduzcas cada caso a mano. Construye un objeto normal y deja que el serializador JSON del lenguaje escriba JSON válido.

Causa 4: patrones de regex almacenados en JSON de configuración

Los regex tienen su propio lenguaje de escape. Las cadenas JSON tienen un lenguaje de escape separado. La barra invertida de la regex tiene que sobrevivir al parseo de JSON antes de poder llegar al motor de regex.

Configuración JSON rota:

{ "datePattern": "^\d{4}-\d{2}-\d{2}$" }

Configuración JSON válida:

{
  "datePattern": "^\\d{4}-\\d{2}-\\d{2}$"
}

Tras el parseo de JSON, la aplicación ve esta cadena:

^\d{4}-\d{2}-\d{2}$

Solo entonces debería convertirse en una expresión regular:

const config = JSON.parse('{"datePattern":"^\\\\d{4}-\\\\d{2}-\\\\d{2}$"}');
const re = new RegExp(config.datePattern);

La misma regla se aplica a \s, \w, \b, grupos con nombre, ejemplos de lookbehind y cadenas de reemplazo. Si la barra invertida está destinada a un parser posterior, dóblala en JSON.

Causa 5: escapes Unicode malformados

El escape Unicode de JSON tiene ancho fijo:

{ "char": "\u12" }

JSON válido:

{
  "char": "\u0012"
}

La u debe ir en minúscula y seguida de exactamente cuatro dígitos hex: 0-9, a-f o A-F.

Estos no son escapes Unicode de JSON:

"\u{2028}"   // JavaScript source style, not JSON
"\U00002028" // Python style, not JSON
"\u20G0"     // G is not a hex digit

Los caracteres fuera del Plano Multilingüe Básico, como muchos emojis y algunos símbolos matemáticos, pueden almacenarse literalmente en JSON UTF-8:

{
  "emoji": "😀"
}

Cuando se escapan, se representan como un par subrogado UTF-16:

{
  "emoji": "\uD83D\uDE00"
}

Evita subrogados sueltos como \uD83D sin el subrogado bajo emparejado. Algunos parsers los aceptan como unidades de código, pero los sistemas posteriores que requieren Unicode bien formado pueden rechazarlos.

Causa 6: cadenas JSON construidas a mano

Esta es la versión de producción del bug:

// Unsafe: userInput may contain backslashes, quotes, or newlines.
const payload = '{"message":"' + userInput + '"}';

Si userInput es C:\Users\Ada, el texto emitido es JSON inválido. Si contiene ", el JSON puede romperse de otra forma. Si contiene un salto de línea crudo, puedes obtener un bad control character en su lugar.

Usa un serializador:

const payload = JSON.stringify({
  message: userInput,
  path: 'C:\\Users\\Ada\\file.json',
  code: '\x1b[32mOK\x1b[0m',
});

JSON.stringify() se encarga del escape específico de JSON. El resultado es texto JSON válido:

{
  "message": "...",
  "path": "C:\\Users\\Ada\\file.json",
  "code": "\u001b[32mOK\u001b[0m"
}

El mismo principio se aplica en otros lenguajes:

import json

payload = json.dumps({
    "path": r"C:\Users\Ada\file.json",
    "pattern": r"^\d+$",
})
body, err := json.Marshal(map[string]string{
    "path": `C:\Users\Ada\file.json`,
    "pattern": `^\d+$`,
})

Si estás arreglando un productor, este es el arreglo real. Parchear JSON inválido aguas abajo solo oculta el lugar donde se creó el texto incorrecto.

Cómo localizar el escape incorrecto

Para JSON pegado, este pequeño helper hace más fácil ver la zona alrededor de la position de V8:

function showJsonParseContext(raw) {
  try {
    JSON.parse(raw);
    console.log('Valid JSON');
  } catch (error) {
    const message = String(error.message);
    const match = message.match(/position (\d+)/);

    if (!match) {
      console.log(message);
      return;
    }

    const pos = Number(match[1]);
    const start = Math.max(0, pos - 24);
    const end = Math.min(raw.length, pos + 24);
    const excerpt = raw.slice(start, end);

    console.log(message);
    console.log(JSON.stringify(excerpt));
    console.log(' '.repeat(pos - start) + '^');
  }
}

const raw = String.raw`{"path":"C:\Users\Ada\file.json"}`;
showJsonParseContext(raw);

JSON.stringify(excerpt) es intencional. Muestra las barras invertidas y los caracteres de control como escapes visibles, que es exactamente lo que necesitas cuando el bug es un espacio en blanco invisible o un escape demasiado agresivo.

Para errores estilo Firefox con line y column, salta primero a esa línea y luego inspecciona el literal de cadena en ella. Si la columna exacta cae después de una barra invertida, lee también el carácter anterior.

¿Herramienta de reparación o rechazar el payload?

Usa una herramienta de reparación cuando:

  • Estás limpiando un fragmento pegado.
  • Estás depurando una línea de log.
  • Estás revisando la salida de un LLM.
  • Puedes confirmar visualmente el valor reparado.
  • El valor no está gestionando movimiento de dinero, permisos, borrado o cambios de estado irreversibles.

Rechaza el payload y arregla el productor cuando:

  • El JSON vino de un contrato de API.
  • El valor afecta a facturación, permisos, seguridad o borrado de datos.
  • El parser tuvo que adivinar entre varios significados posibles.
  • Una ruta, regex o secuencia de escape podría ser válida pero semánticamente incorrecta.

Por ejemplo, reparar C:\Users\Ada\file.json no es solo una operación sintáctica. \f en \file es un escape válido, así que una herramienta puede parsear un carácter form feed en lugar de preservar la barra invertida. Un humano o el código productor debe decidir cuál es la ruta pretendida.

La herramienta JSON Fix de este sitio se usa mejor como asistente de depuración local en el navegador: pega el texto, inspecciona la salida y luego valida el JSON reparado. No debería ser la capa de ingestión silenciosa para payloads de producción malformados.

Cómo desescapar JSON de forma segura

A veces las barras invertidas no son incorrectas; el JSON está doblemente codificado. Puedes ver esto en los logs:

{\"name\":\"Ada\",\"path\":\"C:\\\\Users\\\\Ada\"}

No ejecutes un replace(/\\/g, '') general. Eso destruye los escapes reales.

Parsea una capa de JSON válida cada vez:

// The outer value is a JSON string that contains JSON text.
const wrapped = '"{\\"name\\":\\"Ada\\",\\"path\\":\\"C:\\\\\\\\Users\\\\\\\\Ada\\"}"';

const once = JSON.parse(wrapped);
// once is: {"name":"Ada","path":"C:\\Users\\Ada"}

const data = JSON.parse(once);
// data is: { name: "Ada", path: "C:\\Users\\Ada" }

Si el primer parseo falla con Bad escaped character, la entrada no está simplemente codificada. Es texto JSON inválido y necesita una reparación específica.

Lista de prevención

  • Nunca concatenes cadenas de usuario dentro de JSON.
  • Usa JSON.stringify(), json.dumps(), json.Marshal() o el serializador JSON de tu plataforma.
  • Almacena los patrones de regex en JSON con barras invertidas dobles.
  • Prefiere las barras normales para rutas cuando el consumidor las acepte.
  • Entrecomilla y prueba los ejemplos copiados de logs, shells y documentación.
  • Valida los ficheros .json generados en CI con un parser real.
  • Registra una vista previa segura alrededor de la posición del parser en lugar de registrar el payload completo.
  • Trata la reparación automática como un flujo de desarrollo, no como un contrato de producción.

Preguntas frecuentes

¿Qué significa "Bad escaped character in JSON"?

Una barra invertida dentro de una cadena JSON va seguida de un carácter que JSON no permite tras \. Los escapes válidos son ", \, /, b, f, n, r, t y uXXXX.

¿Cómo arreglo una ruta de Windows en JSON?

Escribe cada barra invertida de la ruta como \\, por ejemplo C:\\Users\\Ada\\file.json. Si el programa receptor acepta barras normales, C:/Users/Ada/file.json es JSON válido y más fácil de leer.

¿Por qué mi regex funciona en JavaScript pero falla en JSON?

El parser de JSON ve la cadena antes que el motor de regex. Un escape de regex como \d debe escribirse como \\d en JSON para que la cadena parseada siga conteniendo \d.

¿Es \x1b JSON válido?

No. \xNN es común en JavaScript, Python y ejemplos de shell, pero JSON no lo admite. Usa \u001b para el carácter ANSI ESC, o elimina los códigos de color ANSI antes de serializar los logs.

¿Es lo mismo que "Bad control character"?

No. "Bad escaped character" significa que el carácter que va después de una barra invertida es inválido. "Bad control character" significa que un byte de control crudo, como un salto de línea, tabulador, NUL o byte ESC literales, aparece dentro de una cadena JSON.

¿Pueden las herramientas de reparación de JSON arreglar automáticamente los bad escapes?

A veces, para fragmentos pegados donde el valor pretendido es obvio. No autorepares silenciosamente payloads de API, datos sensibles a seguridad, pagos, permisos, borrados o valores donde \f, \n o \t puedan ser válidos pero no pretendidos.

¿Cómo desescapo JSON?

Parsea una capa cada vez con JSON.parse(). Un valor doblemente codificado se convierte en una cadena JSON normal tras el primer parseo y en un objeto o array real tras el segundo. Evita eliminar barras invertidas con regex porque corrompe los escapes válidos.

¿Cómo prevengo este error en el código fuente?

Construye valores nativos y serialízalos con JSON.stringify() o el serializador equivalente en tu lenguaje. No ensambles JSON mediante concatenación de cadenas.

Arréglalo ahora

Fuentes

Última revisión: julio de 2026.