JSON: stringify y parse
Introducción
JavaScript Object Notation, conocido como JSON, es un formato de intercambio de datos ligero y fácil de leer tanto para humanos como para máquinas. Se ha convertido en uno de los formatos más populares para transmitir información entre aplicaciones, especialmente en entornos web. JSON se basa en la sintaxis de los objetos de JavaScript, pero es independiente del lenguaje, lo que lo hace ideal para la comunicación entre sistemas escritos en diferentes tecnologías.
En este artículo aprenderemos qué es exactamente JSON, cómo convertir datos de JavaScript a JSON y viceversa utilizando los métodos JSON.stringify()
y JSON.parse()
, y veremos ejemplos prácticos de estos procesos fundamentales para el desarrollo web moderno.
¿Qué es JSON?
JSON (JavaScript Object Notation) es un formato de texto sencillo para el intercambio de datos. Su simplicidad lo ha convertido en una alternativa popular a XML y otros formatos más complejos. JSON se basa en dos estructuras:
- Una colección de pares nombre/valor (similar a un objeto en JavaScript)
- Una lista ordenada de valores (similar a un array en JavaScript)
Ejemplo de un objeto JSON:
{
"nombre": "María",
"edad": 28,
"esEstudiante": false,
"intereses": ["programación", "fotografía", "viajes"],
"direccion": {
"calle": "Gran Vía",
"numero": 42,
"ciudad": "Madrid"
}
}
Diferencias entre objetos JavaScript y JSON
Aunque JSON está basado en la sintaxis de objetos de JavaScript, existen importantes diferencias:
-
Comillas en las claves: En JSON, los nombres de las propiedades deben estar entre comillas dobles. En JavaScript, las comillas son opcionales para identificadores simples.
-
Valores permitidos: JSON solo admite estos tipos de datos:
- Strings (entre comillas dobles)
- Números
- Objetos
- Arrays
- Booleanos (true o false)
- null
-
No soporta: En JSON no puedes usar:
- Funciones
- Fechas (se convierten a strings)
- undefined
- Símbolos
- Objetos con métodos
-
Comentarios: JSON no admite comentarios, a diferencia de JavaScript.
JSON.stringify(): Convertir a JSON
El método JSON.stringify()
convierte un valor de JavaScript en una cadena de texto JSON.
Sintaxis básica:
JSON.stringify(valor, reemplazador, espacio)
Donde:
valor
: El valor que se va a convertir a JSONreemplazador
(opcional): Una función o un array que altera el proceso de conversiónespacio
(opcional): Mejora la legibilidad añadiendo indentación
Ejemplos básicos:
// Objeto simple
const persona = {
nombre: "Carlos",
edad: 35,
activo: true
};
const personaJSON = JSON.stringify(persona);
console.log(personaJSON);
// Resultado: '{"nombre":"Carlos","edad":35,"activo":true}'
// Array
const colores = ["rojo", "verde", "azul"];
const coloresJSON = JSON.stringify(colores);
console.log(coloresJSON);
// Resultado: '["rojo","verde","azul"]'
// Valor simple
console.log(JSON.stringify(42)); // "42"
console.log(JSON.stringify("Hola")); // ""Hola""
console.log(JSON.stringify(true)); // "true"
console.log(JSON.stringify(null)); // "null"
Formateando el resultado con el parámetro de espacio:
const datos = {
nombre: "Elena",
cursos: ["JavaScript", "HTML", "CSS"],
experiencia: {
años: 3,
nivel: "intermedio"
}
};
// Sin formato
console.log(JSON.stringify(datos));
// Con 2 espacios de indentación
console.log(JSON.stringify(datos, null, 2));
// Con un carácter personalizado
console.log(JSON.stringify(datos, null, ".."));
El resultado con indentación hace que el JSON sea mucho más legible:
{
"nombre": "Elena",
"cursos": [
"JavaScript",
"HTML",
"CSS"
],
"experiencia": {
"años": 3,
"nivel": "intermedio"
}
}
Usando el parámetro reemplazador:
Como array:
const usuario = {
nombre: "Pedro",
contraseña: "secreto123",
email: "pedro@ejemplo.com",
edad: 29
};
// Solo incluir estas propiedades
const usuarioFiltrado = JSON.stringify(usuario, ["nombre", "email"]);
console.log(usuarioFiltrado);
// Resultado: '{"nombre":"Pedro","email":"pedro@ejemplo.com"}'
Como función:
const datos = {
nombre: "Ana",
edad: 25,
contraseña: "123456",
fechaNacimiento: new Date(1997, 5, 12)
};
// Función para transformar valores
const reemplazador = (clave, valor) => {
// Ocultar la contraseña
if (clave === "contraseña") {
return "******";
}
// Convertir fecha a formato legible
if (valor instanceof Date) {
return valor.toLocaleDateString();
}
return valor;
};
console.log(JSON.stringify(datos, reemplazador, 2));
Resultado:
{
"nombre": "Ana",
"edad": 25,
"contraseña": "******",
"fechaNacimiento": "12/6/1997"
}
Manejo de tipos especiales
JavaScript tiene tipos de datos que no existen en JSON. Veamos cómo se manejan:
const datosEspeciales = {
funcion: function() { return "Hola"; },
fecha: new Date(),
regexp: /\d+/,
infinito: Infinity,
nan: NaN,
indefinido: undefined,
nulo: null,
simbolo: Symbol("id")
};
console.log(JSON.stringify(datosEspeciales));
// Resultado: '{"fecha":"2023-10-15T10:30:00.000Z","regexp":{},"infinito":null,"nan":null,"nulo":null}'
Como puedes ver:
- Las funciones se omiten
- Las fechas se convierten a strings en formato ISO
- Las expresiones regulares se convierten en objetos vacíos
Infinity
yNaN
se convierten ennull
undefined
ySymbol
se omitennull
se mantiene comonull
JSON.parse(): Convertir desde JSON
El método JSON.parse()
analiza una cadena de texto JSON y la convierte en un objeto JavaScript.
Sintaxis básica:
JSON.parse(texto, revivificador)
Donde:
texto
: La cadena JSON a analizarrevivificador
(opcional): Función que transforma las propiedades y valores durante el proceso
Ejemplos básicos:
// Parsear un objeto
const jsonTexto = '{"nombre":"Laura","edad":31,"ciudad":"Barcelona"}';
const objeto = JSON.parse(jsonTexto);
console.log(objeto.nombre); // "Laura"
console.log(objeto.edad); // 31
// Parsear un array
const jsonArray = '["manzana","naranja","plátano"]';
const frutas = JSON.parse(jsonArray);
console.log(frutas[1]); // "naranja"
console.log(frutas.length); // 3
// Parsear valores simples
console.log(JSON.parse('"texto"')); // "texto"
console.log(JSON.parse('42')); // 42
console.log(JSON.parse('true')); // true
console.log(JSON.parse('null')); // null
Usando el parámetro revivificador:
El revivificador es una función que se ejecuta para cada par clave-valor en el objeto resultante, permitiéndonos transformar valores durante el proceso de análisis.
const jsonData = '{"nombre":"Alberto","nacimiento":"1990-05-15","activo":true}';
const revivificador = (clave, valor) => {
// Convertir string de fecha a objeto Date
if (clave === "nacimiento" && typeof valor === "string") {
return new Date(valor);
}
return valor;
};
const persona = JSON.parse(jsonData, revivificador);
console.log(persona.nacimiento instanceof Date); // true
console.log(persona.nacimiento.getFullYear()); // 1990
Errores comunes y su resolución
1. JSON no válido
Si intentamos analizar una cadena que no es JSON válido, se producirá un error:
try {
// JSON inválido: comillas simples, propiedad sin comillas
const datos = JSON.parse('{nombre: "Juan"}');
} catch (error) {
console.error("Error al parsear JSON:", error.message);
// "Error al parsear JSON: Unexpected token n in JSON at position 1"
}
Solución: Asegúrate de que el JSON cumple con el formato correcto:
- Propiedades entre comillas dobles
- Valores string entre comillas dobles
- Sin comas finales en arrays u objetos
2. Pérdida de tipos específicos
const original = {
fecha: new Date(),
regexp: /hola/,
funcion: function() { return "Mundo"; }
};
const jsonStr = JSON.stringify(original);
const recuperado = JSON.parse(jsonStr);
console.log(recuperado.fecha); // String, no un objeto Date
console.log(typeof recuperado.fecha); // "string"
console.log(recuperado.regexp); // {}, no una expresión regular
console.log(recuperado.funcion); // undefined, la función se perdió
Solución: Usar la función revivificador para reconstruir tipos específicos:
const jsonConFecha = '{"nombre":"Teresa","fecha":"2023-10-15T12:00:00.000Z"}';
const recuperarTipos = (clave, valor) => {
if (clave === "fecha" && typeof valor === "string") {
return new Date(valor);
}
return valor;
};
const objetoConTipos = JSON.parse(jsonConFecha, recuperarTipos);
console.log(objetoConTipos.fecha instanceof Date); // true
Uso en almacenamiento y comunicación
LocalStorage
Uno de los usos más comunes de JSON.stringify
y JSON.parse
es guardar y recuperar datos en el almacenamiento local del navegador:
// Guardar datos
const preferenciasUsuario = {
tema: "oscuro",
tamañoFuente: "grande",
notificaciones: true,
ultimoAcceso: new Date()
};
// Convertir a string para guardar
localStorage.setItem("preferencias", JSON.stringify(preferenciasUsuario));
// Recuperar datos
const preferenciasGuardadas = localStorage.getItem("preferencias");
const preferencias = JSON.parse(preferenciasGuardadas, (clave, valor) => {
if (clave === "ultimoAcceso") return new Date(valor);
return valor;
});
console.log(preferencias.tema); // "oscuro"
console.log(preferencias.ultimoAcceso instanceof Date); // true
Comunicación con API REST
JSON es el formato estándar para la comunicación entre cliente y servidor en las API modernas:
// Enviar datos a un servidor
const nuevoProducto = {
nombre: "Portátil",
precio: 899.99,
stock: 10,
caracteristicas: ["SSD", "16GB RAM", "i7"]
};
fetch("https://api.ejemplo.com/productos", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify(nuevoProducto)
})
.then(respuesta => respuesta.json()) // Parse automático
.then(datos => {
console.log("Producto creado con ID:", datos.id);
})
.catch(error => console.error("Error:", error));
Circulares y estructuras anidadas
Al trabajar con objetos que contienen referencias circulares, JSON.stringify()
lanzará un error:
const objetoA = { nombre: "Objeto A" };
const objetoB = { nombre: "Objeto B" };
// Creamos una referencia circular
objetoA.referencia = objetoB;
objetoB.referencia = objetoA;
try {
const jsonCircular = JSON.stringify(objetoA);
} catch (error) {
console.error("Error:", error.message);
// "TypeError: Converting circular structure to JSON"
}
Solución: Implementar un reemplazador personalizado para eliminar o transformar referencias circulares:
const manejadorCircular = () => {
const visitados = new WeakSet();
return (clave, valor) => {
// Si es un objeto y no es null
if (typeof valor === "object" && valor !== null) {
// Si ya lo visitamos antes, es una referencia circular
if (visitados.has(valor)) {
return "[Referencia Circular]";
}
// Marcamos este objeto como visitado
visitados.add(valor);
}
return valor;
};
};
const objetoA = { nombre: "Objeto A" };
const objetoB = { nombre: "Objeto B" };
objetoA.referencia = objetoB;
objetoB.referencia = objetoA;
// Ahora podemos convertirlo a JSON sin errores
const jsonSeguro = JSON.stringify(objetoA, manejadorCircular(), 2);
console.log(jsonSeguro);
Resumen
JSON (JavaScript Object Notation) es un formato de intercambio de datos ligero, basado en la sintaxis de objetos de JavaScript, pero con algunas limitaciones. JavaScript nos proporciona dos métodos fundamentales para trabajar con JSON:
JSON.stringify()
: Convierte datos de JavaScript a formato de texto JSON, con opciones para personalizar el resultado mediante reemplazadores y formato de salida.JSON.parse()
: Convierte una cadena JSON en un objeto JavaScript, permitiendo transformaciones durante el proceso mediante la función revivificador.
Estos métodos son esenciales para el almacenamiento de datos en el navegador y la comunicación con servicios web, siendo parte fundamental del desarrollo web moderno. Al utilizarlos, es importante tener en cuenta las limitaciones de JSON en cuanto a tipos de datos soportados y manejar adecuadamente casos especiales como las referencias circulares.