Serialización de objetos en TypeScript: guía completa
\n\nLa serialización es el proceso de convertir un objeto en un flujo de bytes o una cadena para transmitirlo por la red o almacenarlo. En TypeScript, esta tarea se complica por la necesidad de preservar los tipos, mantener el polimorfismo y trabajar con clases. Analicemos las principales herramientas y enfoques.
\n\n1. Serialización incorporada: JSON.stringify / JSON.parse
\n\nEl mecanismo básico en JavaScript/TypeScript es el objeto global JSON. Solo serializa tipos simples: cadenas, números, valores booleanos, arreglos y objetos planos. Los métodos, símbolos, undefined, Date e instancias de clases se pierden.
// Ejemplo: serialización de una clase\nclass User {\n constructor(\n public name: string,\n private password: string,\n public createdAt: Date = new Date()\n ) {}\n}\n\nconst user = new User('Alice', 'secret123');\nconst json = JSON.stringify(user);\n// Resultado: {"name":"Alice","createdAt":"2025-03-24T10:00:00.000Z"}\n// password no aparece en JSON (private), pero Date se convierte en cadena\n// Al deserializar, obtenemos un objeto plano, no una instancia de User\n\nconst parsed: User = JSON.parse(json) as User;\nconsole.log(parsed instanceof User); // false\n\n\nProblemas:
\n- \n
- Pérdida de tipo (la instancia de clase se convierte en
object). \n - No se serializan campos privados, métodos, getters. \n
- Fechas, Map, Set, BigInt requieren conversión manual. \n
- El polimorfismo no es compatible: es necesario restaurar el tipo manualmente. \n
2. Biblioteca class-transformer
\n\nclass-transformer es la solución más popular para serializar/deserializar clases en TypeScript. Utiliza decoradores para describir las reglas de transformación.
\n\nInstalación
\nnpm install class-transformer reflect-metadata\n\nEjemplo de uso
\nimport { plainToClass, classToPlain, Expose, Transform, Type } from 'class-transformer';\nimport 'reflect-metadata';\n\nclass Address {\n @Expose()\n city!: string;\n\n @Expose()\n street!: string;\n}\n\nclass Employee {\n @Expose()\n id!: number;\n\n @Expose()\n name!: string;\n\n @Expose()\n @Type(() => Address) // transformación anidada\n address!: Address;\n\n @Expose()\n @Transform(({ value }) => new Date(value)) // transformación personalizada\n hireDate!: Date;\n\n // El método no se serializa\n get displayName(): string {\n return `${this.name} (ID: ${this.id})`;\n }\n}\n\n// Deserialización desde un objeto plano\nconst plainData = {\n id: 1,\n name: 'Bob',\n address: { city: 'Moscow', street: 'Tverskaya' },\n hireDate: '2024-01-15T00:00:00.000Z'\n};\n\nconst employee = plainToClass(Employee, plainData);\nconsole.log(employee instanceof Employee); // true\nconsole.log(employee.hireDate instanceof Date); // true\n\n// Serialización inversa\nconst plain = classToPlain(employee);\nconsole.log(plain); // { id: 1, name: 'Bob', address: { city: 'Moscow', street: 'Tverskaya' }, hireDate: '2024-01-15T00:00:00.000Z' }\n\n\nVentajas:
\n- \n
- Restauración automática de tipos (objetos anidados, arreglos). \n
- Soporte de polimorfismo mediante
@Typecon discriminador. \n - Transformación de valores (fechas, números, formatos personalizados). \n
- Trabajo con campos privados a través de
@Expose. \n
Desventajas:
\n- \n
- Dependencia de decoradores (requiere
experimentalDecoratorsen tsconfig). \n - No es adecuado para sistemas de alta carga (la reflexión ralentiza el rendimiento). \n
- Tamaño del bundle ~15KB (gzip). \n
3. Búferes de protocolo (Protocol Buffers) con protobuf-ts
\n\nPara arquitecturas de microservicios y gRPC, a menudo se utilizan Protocol Buffers. La implementación en TypeScript protobuf-ts genera código tipado
También en la biblioteca
Hibernate ORM: Potente herramienta para trabajar con bases de datos en Java
Echo para Go: guía completa con ejemplos
Cliente OAuth para Java: ScribeJava y Spring Security OAuth2
Biblioteca GraphQL en C++: implementación de API con graphql-cpp
Generación de códigos QR en C++: biblioteca QR-Code-generator