TypeScript: Deserialisieren von JSON in Klassen mit Typüberprüfung für Eigenschaften

Hallo Habr! Ich möchte meine Bibliothek zum Deserialisieren von JSON-Objekten in Klassen mit Ihnen teilen, die auch Eingabedaten automatisch nach Typ validiert.

Vor nicht allzu langer Zeit erschien eine so wunderbare Sache wie Klassen in JavaScript, was das Schreiben von Code erheblich vereinfachte. Leider wurde die Funktionalität zum Deserialisieren von JSON in dieselben Klassen nicht angezeigt, d. H. Sie können eine Klasse in eine Zeichenfolge serialisieren, aber wieder selbst. Und um diesen Nachteil zu beheben, wurde die ts-serialisierbare Bibliothek geschrieben, die ich mit Ihnen teilen möchte.

Das Wesentliche des Problems wird durch den folgenden Code dargestellt:

export class User { public firstName: string = ""; public lastName: string = ""; public birthDate: Date = new Date(); public getFullName(): string { return [this.firstName, this.lastName].join(' '); } public getAge(): number { return new Date().getFullYear() - this.birthDate.getFullYear(); } } const ivan = new User(); ivan.getFullName(); //   ivan.getAge(); //   ivan instanceof User; //    const text = JSON.stringify(ivan); //     const newIvan = JSON.parse(text); //   newIvan.getFullName(); // :  getFullName  newIvan.getAge(); // :  getAge  newIvan instanceof User; //     

Was ist die Ursache für die Fehler des neuen Ivan? Tatsache ist, dass die JSON.parse-Methode nicht in die User-Klasse deserialisiert wird, sondern in die Object-Klasse, die einfach nicht über die Methoden getFullName und getAge verfügt.

Wie hilft meine Bibliothek, dieses Problem zu lösen und es in User anstatt in Object zu deserialisieren? Es reicht aus, den Code nur geringfügig zu ändern:

 import { jsonProperty, Serializable } from "ts-serializable"; export class User extends Serializable { @jsonProperty(String) public firstName: string = ""; @jsonProperty(String) public lastName: string = ""; @jsonProperty(Date) public birthDate: Date = new Date(); public getFullName(): string { return [this.firstName, this.lastName].join(' '); } public getAge(): number { return new Date().getFullYear() - this.birthDate.getFullYear(); } } const ivan = new User(); ivan.getFullName(); //   ivan.getAge(); //   ivan instanceof User; //    const text = JSON.stringify(ivan); //     const newIvan = new User().fromJson(JSON.parse(text)); //    User newIvan.getFullName(); //   newIvan.getAge(); //   newIvan instanceof User; //    

Alles ist sehr einfach. Wir erben unsere Klasse von der Serializable-Klasse, die zwei fromJson-Methoden für die Deserialisierung und toJSON für die Serialisierung enthält, und legen den @ jsonProperty-Dekorator mit den Eigenschaften auf, die von JSON akzeptiert werden dürfen. Ungültige Daten werden ignoriert, eine Warnung wird an die Konsole ausgegeben und der Standardwert bleibt in der Eigenschaft.

Das ist es im Grunde. Jetzt können Sie vorne genauso einfach deserialisieren und serialisieren wie in C #, Java und anderen Sprachen. Basierend auf dem Verhalten von Newtonsoft Json.NET.

FAQ


Warum von Serializable erben?

Um dem Modell zwei fromJson- und toJSON-Methoden hinzuzufügen. Sie können dasselbe durch Dekorieren oder Dekorieren von Affen tun. Die Vererbung ist jedoch eine geeignetere Methode für Typescript.

Wie die Datenvalidierung erfolgt

Im Dekorator müssen Sie einen Konstruktor der Datentypen zuweisen, die von JSON akzeptiert werden dürfen. Boolean-, String- und Number-Objekte geben Boolean-, String- bzw. Number-Objekte zurück. Wenn Sie ein Array akzeptieren müssen, wird der Typ durch die Klammern des Arrays eingerahmt, z. B. @jsonProperty ([String]). Wenn der Konstruktor von der Serializable-Klasse geerbt wird, wird er auch in die Klasse deserialisiert. Andernfalls wird das Objekt zurückgegeben.

Wie kann man Validierungsfehler abfangen?

Standardmäßig schreibt die Bibliothek einfach Warnungen über Validierungsfehler in die Konsole. Um dieses Verhalten zu überschreiben, z. B. das Auslösen von Ausnahmen oder das Protokollieren im Backend, müssen Sie die onWrongType-Methode des Modells überschreiben.

Bonus 1. Tiefe Kopie.


 const user1 = new Uesr(); const user2 = new User().fromJson(user1); //    

Bonus 2. Lazy ViewModels.


Wenn Sie ein Modell mit zusätzlichen Daten erstellen müssen, z. B. für Ansichten, die vom Backend jedoch nicht akzeptiert werden, können Sie das Modell einfach um neue Eigenschaften erweitern und diese Eigenschaften mit dem Dekorator @jsonIgnore markieren. Und dann werden diese Eigenschaften nicht serialisiert.

 import { jsonProperty, Serializable } from "ts-serializable"; export class User extends Serializable { @jsonProperty(String) public firstName: string = ""; @jsonIgnore() public isExpanded: boolean = false; } JSON.stringify(new User()); //  {"firstName":""} 

Source: https://habr.com/ru/post/de428812/


All Articles