Objektserialisierung in TypeScript: Vollständige Anleitung
\n\nSerialisierung ist der Prozess der Umwandlung eines Objekts in einen Bytestrom oder eine Zeichenkette zur Übertragung über ein Netzwerk oder zur Speicherung. In TypeScript wird diese Aufgabe durch die Notwendigkeit erschwert, Typen zu erhalten, Polymorphismus zu unterstützen und mit Klassen zu arbeiten. Wir betrachten die wichtigsten Werkzeuge und Ansätze.
\n\n1. Integrierte Serialisierung: JSON.stringify / JSON.parse
\n\nDer grundlegende Mechanismus in JavaScript/TypeScript ist das globale Objekt JSON. Es serialisiert nur einfache Typen: Zeichenketten, Zahlen, boolesche Werte, Arrays und flache Objekte. Methoden, Symbole, undefined, Date und Instanzen von Klassen gehen verloren.
// Beispiel: Serialisierung einer Klasse\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// Ergebnis: {"name":"Alice","createdAt":"2025-03-24T10:00:00.000Z"}\n// password ist nicht im JSON (private), aber Date wurde zu einem String\n// Bei der Deserialisierung erhalten wir ein gewöhnliches Objekt, keine Instanz von User\n\nconst parsed: User = JSON.parse(json) as User;\nconsole.log(parsed instanceof User); // false\n\n\nProbleme:
\n- \n
- Typverlust (eine Klasseninstanz wird zu
object). \n - Private Felder, Methoden und Getter werden nicht serialisiert. \n
- Dates, Map, Set, BigInt erfordern manuelle Konvertierung. \n
- Polymorphismus wird nicht unterstützt – der Typ muss manuell wiederhergestellt werden. \n
2. Bibliothek class-transformer
\n\nclass-transformer ist die beliebteste Lösung für die Serialisierung/Deserialisierung von Klassen in TypeScript. Sie verwendet Dekorateure zur Beschreibung der Transformationsregeln.
\n\nInstallation
\nnpm install class-transformer reflect-metadata\n\nAnwendungsbeispiel
\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) // verschachtelte Transformation\n address!: Address;\n\n @Expose()\n @Transform(({ value }) => new Date(value)) // benutzerdefinierte Transformation\n hireDate!: Date;\n\n // Methode wird nicht serialisiert\n get displayName(): string {\n return `${this.name} (ID: ${this.id})`;\n }\n}\n\n// Deserialisierung aus einem Plain-Objekt\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// Serialisierung zurück\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\nVorteile:
\n- \n
- Automatische Wiederherstellung von Typen (verschachtelte Objekte, Arrays). \n
- Unterstützung von Polymorphismus durch
@Typemit Diskriminator. \n - Werttransformation (Daten, Zahlen, benutzerdefinierte Formate). \n
- Arbeit mit privaten Feldern über
@Expose. \n
Nachteile:
\n- \n
- Abhängigkeit von Dekorateuren (erfordert
experimentalDecoratorsin tsconfig). \n - Nicht geeignet für hochbelastete Systeme (Reflexion verlangsamt die Arbeit). \n
- Bündelgröße ~15KB (gzip). \n
3. Protocol Buffers mit protobuf-ts
\n\nFür Mikroservice-Architekturen und gRPC werden häufig Protocol Buffers verwendet. Die TypeScript-Implementierung protobuf-ts generiert typisierte