TypeScript 对象序列化:完整指南
序列化是将对象转换为字节流或字符串以便于网络传输或存储的过程。在 TypeScript 中,这一任务因需要保留类型、支持多态性以及处理类而变得更加复杂。下面我们来探讨主要的工具和方法。
1. 内置序列化:JSON.stringify / JSON.parse
JavaScript/TypeScript 中的基本机制是全局对象 JSON。它只能序列化简单类型:字符串、数字、布尔值、数组和扁平对象。方法、符号、undefined、Date 以及类的实例都会丢失。
// 示例:类的序列化class User { constructor( public name: string, private password: string, public createdAt: Date = new Date() ) {}}
const user = new User('Alice', 'secret123');const json = JSON.stringify(user);// 结果:{"name":"Alice","createdAt":"2025-03-24T10:00:00.000Z"}// password 未包含在 JSON 中(private),但 Date 变成了字符串// 反序列化时,我们将得到一个普通对象,而非 User 实例
const parsed: User = JSON.parse(json) as User;console.log(parsed instanceof User); // false问题:
- 类型丢失(类实例变成了
object)。 - 私有字段、方法、getter 无法序列化。
- Date、Map、Set、BigInt 需要手动转换。
- 不支持多态性——需要手动恢复类型。
2. class-transformer 库
class-transformer 是 TypeScript 中最流行的类序列化/反序列化解决方案。它使用装饰器来描述转换规则。
安装
npm install class-transformer reflect-metadata使用示例
import { plainToClass, classToPlain, Expose, Transform, Type } from 'class-transformer';import 'reflect-metadata';
class Address { @Expose() city!: string;
@Expose() street!: string;}
class Employee { @Expose() id!: number;
@Expose() name!: string;
@Expose() @Type(() => Address) // 嵌套转换 address!: Address;
@Expose() @Transform(({ value }) => new Date(value)) // 自定义转换 hireDate!: Date;
// 方法不会被序列化 get displayName(): string { return `${this.name} (ID: ${this.id})`; }}
// 从普通对象反序列化const plainData = { id: 1, name: 'Bob', address: { city: 'Moscow', street: 'Tverskaya' }, hireDate: '2024-01-15T00:00:00.000Z'};
const employee = plainToClass(Employee, plainData);console.log(employee instanceof Employee); // trueconsole.log(employee.hireDate instanceof Date); // true
// 序列化回普通对象const plain = classToPlain(employee);console.log(plain); // { id: 1, name: 'Bob', address: { city: 'Moscow', street: 'Tverskaya' }, hireDate: '2024-01-15T00:00:00.000Z' }优点:
- 自动恢复类型(嵌套对象、数组)。
- 通过带鉴别器的
@Type支持多态性。 - 值转换(日期、数字、自定义格式)。
- 通过
@Expose处理私有字段。
缺点:
- 依赖装饰器(需要在 tsconfig 中启用
experimentalDecorators)。 - 不适用于高负载系统(反射会降低性能)。
- 打包体积约 15KB(gzip)。
3. Protocol Buffers 与 protobuf-ts
对于微服务架构和 gRPC,通常使用 Protocol Buffers。TypeScript 实现 protobuf-ts 可生成类型化