CAP 14 · LEC 01·Bonus prácticos

JSON: serialización y deserialización de datos

JSON es el formato universal de intercambio de datos en la web. Aprende a convertir entre objetos JavaScript y texto JSON, y a personalizar la serialización para casos avanzados.

● PRINCIPIANTE6 min lectura4 ejerciciospor Fernando Herrera · actualizado mayo de 2026
¿Encontraste un error o algo que mejorar?Editá esta lección en GitHub →

¿Qué es JSON?

JSON (JavaScript Object Notation) es un formato de texto para representar datos estructurados. Es el estándar de facto para APIs REST, archivos de configuración y almacenamiento de datos.

// JSON es texto — un string con estructura específica const jsonString = `{ "nombre": "Ana García", "edad": 28, "activo": true, "cursos": ["JavaScript", "TypeScript"], "direccion": null }`; // JSON soporta estos tipos: // string, number, boolean, null, array, object // No soporta: undefined, Date, Function, Symbol // Tipos válidos en JSON: const ejemploJSON = { texto: "hola", // string ✅ numero: 42, // number ✅ decimal: 3.14, // number ✅ booleano: true, // boolean ✅ nulo: null, // null ✅ lista: [1, "dos", true], // array ✅ objeto: { a: 1 }, // object ✅ }; // Tipos que se PIERDEN en JSON: // undefined → desaparece // Date → se convierte a string ISO // Function → desaparece // Symbol → desaparece
// TypeScript puede tipar la estructura JSON esperada interface UsuarioJSON { nombre: string; edad: number; activo: boolean; cursos: string[]; direccion: string | null; } // El tipo genérico de JSON en TypeScript type JSONValue = | string | number | boolean | null | JSONValue[] | { [key: string]: JSONValue }; // JSON válido tipado const datos: UsuarioJSON = { nombre: "Ana García", edad: 28, activo: true, cursos: ["JavaScript", "TypeScript"], direccion: null, }; console.log(datos.nombre); // "Ana García"

JSON.parse() — string a objeto

JSON.parse() convierte un string JSON en un objeto JavaScript. Si el string no es JSON válido, lanza un SyntaxError.

const respuestaAPI = `{ "id": 1, "usuario": "ana_garcia", "puntos": 1250, "nivel": "intermedio", "ultimaConexion": "2026-05-02T10:30:00.000Z" }`; // Convertir a objeto const datos = JSON.parse(respuestaAPI); console.log(datos.usuario); // "ana_garcia" console.log(datos.puntos); // 1250 console.log(typeof datos.puntos); // "number" // ⚠️ Los arrays también son JSON válido const listaJSON = '["JavaScript", "TypeScript", "React"]'; const lista = JSON.parse(listaJSON); console.log(lista[0]); // "JavaScript" console.log(Array.isArray(lista)); // true // Manejo seguro de errores function parsearSeguro(texto) { try { return { ok: true, datos: JSON.parse(texto) }; } catch (error) { return { ok: false, error: error.message }; } } const resultado = parsearSeguro("esto no es json"); console.log(resultado.ok); // false console.log(resultado.error); // "Unexpected token..."
interface DatosUsuario { id: number; usuario: string; puntos: number; nivel: string; ultimaConexion: string; } const respuestaAPI = `{ "id": 1, "usuario": "ana_garcia", "puntos": 1250, "nivel": "intermedio", "ultimaConexion": "2026-05-02T10:30:00.000Z" }`; // JSON.parse retorna 'any' — necesitas hacer el cast o validar const datos = JSON.parse(respuestaAPI) as DatosUsuario; console.log(datos.usuario); // "ana_garcia" console.log(datos.puntos); // 1250 // Función segura con generics function parsearSeguro<T>(texto: string): { ok: true; datos: T } | { ok: false; error: string } { try { return { ok: true, datos: JSON.parse(texto) as T }; } catch (error) { return { ok: false, error: (error as Error).message }; } } const resultado = parsearSeguro<DatosUsuario>(respuestaAPI); if (resultado.ok) { console.log(resultado.datos.usuario); // TypeScript sabe el tipo }
Salidaana_garcia 1250 number JavaScript true false Unexpected token...

JSON.stringify() — objeto a string

JSON.stringify() convierte un objeto JavaScript a su representación JSON como string.

const usuario = { nombre: "Carlos López", puntos: 850, activo: true, cursos: ["JS", "TS"], // Estos se omiten o transforman: clave: undefined, // → omitida fn: () => "hola", // → omitida creado: new Date(), // → string ISO }; // Básico — una línea const compacto = JSON.stringify(usuario); console.log(compacto); // {"nombre":"Carlos López","puntos":850,"activo":true,"cursos":["JS","TS"],"creado":"..."} // Con indentación — legible para humanos const legible = JSON.stringify(usuario, null, 2); console.log(legible); // { // "nombre": "Carlos López", // "puntos": 850, // ... // } // Truco para clonar objetos simples (sin funciones, fechas especiales) const original = { a: 1, b: [2, 3], c: { d: 4 } }; const clon = JSON.parse(JSON.stringify(original)); clon.b.push(99); console.log(original.b); // [2, 3] — no mutado console.log(clon.b); // [2, 3, 99]
interface Configuracion { tema: string; idioma: string; notificaciones: boolean; puntosMinimos: number; } const config: Configuracion = { tema: "oscuro", idioma: "es", notificaciones: true, puntosMinimos: 100, }; // Serializar para guardar en localStorage / API const configJSON: string = JSON.stringify(config, null, 2); console.log(configJSON); // Restaurar — con tipo explícito const configRestaurada = JSON.parse(configJSON) as Configuracion; console.log(configRestaurada.tema); // "oscuro" // Clonar deep copy básico function clonarProfundo<T>(obj: T): T { return JSON.parse(JSON.stringify(obj)); } const original = { a: 1, b: [2, 3] }; const clon = clonarProfundo(original); clon.b.push(99); console.log(original.b); // [2, 3] console.log(clon.b); // [2, 3, 99]
Salida{"nombre":"Carlos López","puntos":850,...} [2, 3] [2, 3, 99]

Replacer y reviver — personalizar la conversión

El segundo argumento de stringify es el replacer (filtrar/transformar al serializar), y el segundo argumento de parse es el reviver (transformar al deserializar).

// Replacer como array — incluir solo ciertas propiedades const usuario = { id: 1, nombre: "Ana", password: "secreto123", // ¡no queremos exponer esto! email: "ana@ejemplo.com", puntos: 500, }; const seguro = JSON.stringify(usuario, ["id", "nombre", "email"]); console.log(seguro); // {"id":1,"nombre":"Ana","email":"ana@ejemplo.com"} // Replacer como función — transformación personalizada const conMascara = JSON.stringify(usuario, (clave, valor) => { if (clave === "password") return undefined; // omitir if (clave === "email") return valor.replace(/(.+)@/, "***@"); // enmascarar return valor; }); console.log(conMascara); // {"id":1,"nombre":"Ana","password":undefined,"email":"***@ejemplo.com","puntos":500} // Reviver — transformar al parsear const jsonConFechas = `{ "titulo": "Mi proyecto", "creado": "2026-01-15T00:00:00.000Z", "modificado": "2026-05-02T10:00:00.000Z" }`; const datos = JSON.parse(jsonConFechas, (clave, valor) => { if (clave === "creado" || clave === "modificado") { return new Date(valor); // string → Date } return valor; }); console.log(datos.creado instanceof Date); // true console.log(datos.creado.getFullYear()); // 2026
interface Proyecto { titulo: string; creado: Date; modificado: Date; } const jsonConFechas = `{ "titulo": "Mi proyecto", "creado": "2026-01-15T00:00:00.000Z", "modificado": "2026-05-02T10:00:00.000Z" }`; // Reviver convierte strings de fecha a Date const datosRaw = JSON.parse(jsonConFechas, (clave: string, valor: unknown) => { if ((clave === "creado" || clave === "modificado") && typeof valor === "string") { return new Date(valor); } return valor; }) as Proyecto; console.log(datosRaw.creado instanceof Date); // true console.log(datosRaw.creado.getFullYear()); // 2026 // Replacer tipado para omitir campos interface UsuarioPublico { id: number; nombre: string; email: string; } const usuario = { id: 1, nombre: "Ana", password: "secreto", email: "ana@ej.com" }; const camposPublicos: (keyof typeof usuario)[] = ["id", "nombre", "email"]; const publico = JSON.stringify(usuario, camposPublicos); console.log(publico); // {"id":1,"nombre":"Ana","email":"ana@ej.com"}
Salida{"id":1,"nombre":"Ana","email":"ana@ejemplo.com"} true 2026

Practica