Сериализация объектов в TypeScript: Полное руководство

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Сериализация объектов в TypeScript: от JSON до protobuf

Сериализация — это процесс преобразования сложной структуры данных (объекта, массива, экземпляра класса) в формат, пригодный для хранения или передачи по сети. Обратный процесс — десериализация — восстанавливает объект из этого формата. В TypeScript, который является строго типизированной надстройкой над JavaScript, сериализация приобретает особое значение: важно не только передать данные, но и сохранить типы, методы и структуру классов.

В этой статье мы рассмотрим основные подходы и инструменты для сериализации объектов в 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} (${this.category}) - ${this.price} руб.`;
  }
}

// Десериализация
const plainProduct = {
  id: 1,
  name: "Ноутбук",
  category: "электроника",
  price_with_tax: 75000
};

const productInstance = plainToClass(Product, plainProduct);
console.log(productInstance.getInfo()); // Ноутбук (ЭЛЕКТРОНИКА) - 75000 руб.

// Сериализация
const serialized = classToPlain(productInstance, { excludeExtraneousValues: true });
console.log(serialized);
// { id: 1, name: 'Ноутбук', category: 'ЭЛЕКТРОНИКА', price_with_tax: 75000 }

Ключевые возможности:

  • Декораторы: @Expose (включает поле), @Exclude (исключает), @Transform (кастомное преобразование), @Type (указывает тип для вложенных объектов).
  • Поддержка вложенных объектов и

Рекомендаций