TypeScript 对象序列化:完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

TypeScript 对象序列化:从 JSON 到 protobuf



序列化是将复杂的数据结构(对象、数组、类实例)转换为适合存储或网络传输格式的过程。反向过程——反序列化——则从该格式恢复对象。在作为 JavaScript 严格类型化超集的 TypeScript 中,序列化尤为重要:不仅需要传输数据,还要保留类型、方法和类结构。



在本文中,我们将探讨 TypeScript 中对象序列化的主要方法和工具,从内置功能到专门的库。



1. 原生序列化:JSON.stringify 和 JSON.parse



最简单且最常用的方法是使用内置方法 JSON.stringify() 和 JSON.parse()。然而,这种方法存在一些限制:



  • 无法序列化函数、undefined、Symbol、BigInt(在旧版本中)。
  • 不保留对象的原型——反序列化后你将得到一个普通对象,而不是类实例。
  • 循环引用会导致错误。


// 简单序列化示例interface User {  id: number;  name: string;  email: string;}

const user: User = { id: 1, name: "伊万", email: "ivan@example.com"};

const jsonString = JSON.stringify(user);console.log(jsonString); // {"id":1,"name":"伊万","email":"ivan@example.com"}

const parsedUser: User = JSON.parse(jsonString);console.log(parsedUser.name); // 伊万


对于简单数据,这已经足够,但如果你需要处理类,则需要更高级的解决方案。



2. 使用 toJSON 和 fromJSON 方法的自定义序列化



TypeScript(以及 JavaScript)允许在类中定义 toJSON() 方法,该方法会在通过 JSON.stringify 序列化时被调用。对于反序列化,可以创建一个静态方法 fromJSON。



class Person {  constructor(    public firstName: string,    public lastName: string,    public age: number  ) {}

// 序列化方法 toJSON() { return { fullName: `${this.firstName} ${this.lastName}`, age: this.age }; }

// 反序列化静态方法 static fromJSON(json: any): Person { const [firstName, lastName] = json.fullName.split(' '); return new Person(firstName, lastName, json.age); }}

const person = new Person("安娜", "彼得罗娃", 30);const json = JSON.stringify(person);console.log(json); // {"fullName":"安娜 彼得罗娃","age":30}

const restoredPerson = Person.fromJSON(JSON.parse(json));console.log(restoredPerson.firstName); // 安娜


这种方法提供了完全的控制权,但需要为每个类编写样板代码。



3. class-transformer 库



class-transformer 是 TypeScript 中最流行的序列化/反序列化库之一。它允许通过装饰器将普通对象转换为类实例,反之亦然。



安装:

npm install class-transformer reflect-metadata


使用示例:



import { plainToClass, classToPlain, Expose, Transform } from "class-transformer";import "reflect-metadata";

class Product { @Expose() id: number;

@Expose() name: string;

@Expose() @Transform(({ value }) => value.toUpperCase()) // 自定义转换 category: string;

@Expose({ name: "price_with_tax" }) // 字段重命名 price: number;

constructor(id: number, name: string, category: string, price: number) { this.id = id; this.name = name; this.category = category; this.price = price; }

getInfo(): string { return `${this.name} (${th

推荐