Menu

JSON en JavaScript: JSON.stringify y JSON.parse

Cómo convertir objetos de JavaScript a JSON y viceversa con JSON.stringify y JSON.parse, usar replacer y reviver, y evitar los valores que no sobreviven al ida y vuelta.

JSON en JavaScript: es texto, no un objeto

JSON (JavaScript Object Notation) es un formato de texto para intercambiar datos. Se parece mucho a un objeto literal de JavaScript, pero en realidad es una cadena: una secuencia de caracteres que puedes enviar por la red, guardar en un archivo o pegar en un fichero de configuración.

// A JavaScript object — a live value in memory.
const user = { name: "Rosa", age: 30 };

// JSON — a string of text that represents the same data.
const json = '{"name":"Rosa","age":30}';

Es fácil confundirlos porque se parecen mucho. El modelo mental que te va a salvar es este: los objetos viven dentro de tu programa; el JSON es cómo se ven cuando salen a la calle. Para pasar de uno a otro tienes dos funciones: JSON.stringify (de objeto a string) y JSON.parse (de string a objeto).

JSON.stringify: convertir un objeto a JSON en JavaScript

Convierte cualquier valor de JavaScript en su representación JSON:

index.js
Output
Click Run to see the output here.

El resultado es una cadena en una sola línea y sin espacios: compacta, perfecta para mandar por la red. El typeof lo confirma: string, no object.

Si lo que quieres es leerlo con comodidad mientras depuras, pásale dos argumentos extra. El segundo es un replacer (ya llegaremos a eso); al pasar null le estás diciendo "inclúyelo todo". El tercero es la indentación:

index.js
Output
Click Run to see the output here.

Ese es el formato estándar de pretty print. Usa 2 o 4 espacios: coincide con lo que generan la mayoría de las herramientas.

JSON.parse: de string a objeto

La operación inversa: le pasas un string JSON y recuperas un valor de JavaScript.

index.js
Output
Click Run to see the output here.

Una vez parseado, trabajas con un objeto normal y corriente: acceso con punto, con corchetes, métodos de array... lo de siempre.

JSON.parse es bastante tiquismiquis. Todos estos casos lanzan un SyntaxError:

JSON.parse("{name: 'Rosa'}");      // unquoted key, single quotes
JSON.parse('{"name": "Rosa",}');   // trailing comma
JSON.parse("// a comment\n{}");    // comments aren't allowed
JSON.parse("");                    // empty string

Siempre que los datos vengan de fuera de tu programa —una respuesta de fetch, un archivo o lo que escriba el usuario— envuelve el parseo en un try/catch:

index.js
Output
Click Run to see the output here.

Valores que no sobreviven al ida y vuelta

JSON soporta seis tipos de valores: cadenas, números, booleanos, null, arrays y objetos planos. Todo lo demás que exista en JavaScript se pierde, se transforma o directamente rompe la serialización.

index.js
Output
Click Run to see the output here.

Qué pasa en realidad:

  • Las funciones y undefined se eliminan silenciosamente de los objetos. Dentro de arrays se convierten en null, ya que los arrays no pueden tener huecos en JSON.
  • Los objetos Date se serializan como una cadena ISO mediante su método toJSON. Al parsearlos recuperas la cadena, no un Date.
  • BigInt lanza un TypeError. Los números de JSON no tienen un equivalente.
  • Map, Set y las referencias circulares tampoco funcionan de entrada.

Para que un Date sobreviva al viaje de ida y vuelta, la solución es la función reviver de JSON.parse:

index.js
Output
Click Run to see the output here.

El reviver se ejecuta para cada par clave/valor y te permite transformar los valores a medida que entran.

El replacer: filtrar qué se serializa

El segundo argumento de JSON.stringify te permite controlar qué acaba en la salida. Pasa un array de claves para incluir solo esas en una especie de lista blanca:

index.js
Output
Click Run to see the output here.

O pásale una función para aplicar la lógica que quieras: descartar campos, enmascarar valores o transformarlos al vuelo:

index.js
Output
Click Run to see the output here.

Si devuelves undefined, la clave se elimina. Cualquier otro valor que retornes la reemplaza.

Personalizar la serialización con toJSON

Cuando un objeto tiene un método toJSON, JSON.stringify lo invoca y serializa lo que ese método devuelva, en lugar del objeto original. Así es como Date define su propio formato, y tú puedes aprovechar este mismo gancho en tus objetos:

index.js
Output
Click Run to see the output here.

Perfecto para clases que quieren mantener una forma pública consistente sin importar quién las serialice.

Clonado profundo (el truco de siempre y uno mejor)

Durante años, JSON.parse(JSON.stringify(obj)) fue el one-liner clásico para hacer un deep clone de un objeto plano:

index.js
Output
Click Run to see the output here.

Funciona, pero solo si el objeto contiene valores compatibles con JSON. Las fechas, los Map y las funciones lo rompen todo (mira los problemas de ida y vuelta que vimos antes).

El JavaScript moderno trae structuredClone, que sí soporta Date, Map, Set, arrays tipados e incluso referencias circulares:

index.js
Output
Click Run to see the output here.

Tira de structuredClone siempre que puedas. Guárdate el truco del JSON.parse(JSON.stringify(...)) por si necesitas clonar datos planos de forma rápida y sin complicaciones.

Un ejemplo realista: hacer fetch y parsear JSON en JavaScript

El sitio donde más vas a toparte con JSON es en las peticiones HTTP. fetch no parsea el JSON por ti: tienes que llamar a .json() sobre la respuesta (que por dentro no es más que un JSON.parse aplicado al cuerpo de la respuesta):

index.js
Output
Click Run to see the output here.

Enviar JSON es el caso inverso: pásale el cuerpo a JSON.stringify y define la cabecera Content-Type.

await fetch("/api/users", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({ name: "Rosa", age: 30 }),
});

Con estos dos patrones cubres la mayoría de los casos reales cuando trabajas con JSON.

Lo que viene: optional chaining

El JSON que parseas suele traer campos opcionales: un user.address.city que puede no existir, un response.data.items que quizá venga vacío. Para acceder a propiedades anidadas sin que todo reviente está el optional chaining (?.), y justo de eso hablamos en la siguiente página.

Preguntas frecuentes

¿Qué diferencia hay entre JSON y un objeto de JavaScript?

JSON es un formato de texto: una cadena que se parece a un literal de objeto de JavaScript pero con reglas más estrictas. Las claves van entre comillas dobles, las cadenas también, y los valores se limitan a strings, números, booleanos, null, arrays y objetos planos. Un objeto de JavaScript, en cambio, es un valor vivo en memoria que puede contener funciones, undefined, instancias de Date y cualquier otra cosa.

¿Cómo convierto un objeto de JavaScript a JSON?

Usa JSON.stringify(obj). Recorre el objeto y devuelve una cadena JSON. Si le pasas un tercer argumento, por ejemplo JSON.stringify(obj, null, 2), obtienes una salida con sangría de 2 espacios, mucho más legible. Ojo: las funciones y los valores undefined se eliminan de los objetos y se convierten en null cuando están dentro de un array.

¿Por qué me lanza error JSON.parse?

JSON.parse es muy estricto: las comas finales, las comillas simples, las claves sin comillas y los comentarios provocan un SyntaxError. Envuelve siempre la llamada en un try/catch cuando la cadena venga de una petición de red, de un archivo o del usuario, es decir, en cualquier caso en que no puedas garantizar que el JSON sea válido.

¿JSON.stringify conserva las fechas (Date)?

No. Un Date se convierte en una cadena ISO tipo "2026-01-15T10:30:00.000Z". Cuando vuelves a hacer JSON.parse, recuperas esa cadena, no un objeto Date. Si necesitas la fecha de verdad, usa el argumento reviver de JSON.parse para detectar esas cadenas ISO y reconstruir el Date.

Aprende a programar con Coddy

COMENZAR