Bonjour, Habr! Je veux partager avec vous ma bibliothèque de désérialisation des objets JSON en classes, qui valide également automatiquement les données d'entrée par type.
Il n'y a pas si longtemps, une chose aussi merveilleuse que les classes est apparue en JavaScript, ce qui a grandement simplifié le processus d'écriture de code. Mais malheureusement, la fonctionnalité de désérialisation de JSON dans ces mêmes classes n'est pas apparue, c'est-à-dire Vous pouvez sérialiser une classe en chaîne, mais de nouveau par vous-même. Et pour corriger cet inconvénient, la bibliothèque
ts-sérialisable a été écrite que je veux partager avec vous.
L'essence du problème est illustrée par le code suivant:
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();
Quelle est la cause des erreurs du nouvel Ivan? Le fait est que la méthode JSON.parse ne désérialise pas la classe User, mais la classe Object, qui n'a tout simplement pas les méthodes getFullName et getAge.
Comment ma bibliothèque aide-t-elle à résoudre ce problème et à le désérialiser dans l'utilisateur plutôt que dans l'objet? Il suffit de modifier légèrement le code:
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; //
Tout est très simple. Nous héritons de notre classe de la classe Serializable, qui a deux méthodes fromJson pour la désérialisation et toJSON pour la sérialisation, et nous raccrochons le décorateur @jsonProperty avec les propriétés autorisées à accepter des données de JSON. Les données non valides seront ignorées, un avertissement sera émis vers la console et la valeur par défaut restera dans la propriété.
C'est essentiellement ça. À l'avant, vous pouvez désérialiser et sérialiser aussi facilement que vous le faites en C #, Java et dans d'autres langages. Basé sur le comportement de Newtonsoft Json.NET.
FAQ
Pourquoi hériter de Serializable?Afin d'ajouter deux méthodes fromJson et toJSON au modèle. Vous pouvez faire de même grâce à la décoration ou au patching de singe. Mais l'héritage est une méthode plus appropriée pour Typescript.
Comment se produit la validation des donnéesDans le décorateur, vous devez affecter un constructeur des types de données autorisés à être acceptés à partir de JSON. Les objets Boolean, String, Number renverront respectivement booléen, string, number. Si vous devez accepter un tableau, le type est encadré par les crochets du tableau, par exemple @jsonProperty ([String]). Si le constructeur est hérité de la classe Serializable, il sera également désérialisé dans la classe, sinon, l'objet sera retourné.
Comment détecter les erreurs de validation?Par défaut, la bibliothèque écrit simplement des avertissements sur la console concernant les erreurs de validation. Pour remplacer ce comportement, comme lever des exceptions ou se connecter au backend, vous devez remplacer la méthode onWrongType du modèle.
Bonus 1. Copie complète.
const user1 = new Uesr(); const user2 = new User().fromJson(user1);
Bonus 2. ViewModels paresseux.
Si vous devez créer un modèle avec des données supplémentaires, par exemple pour les vues, mais que le backend n'accepte pas, vous pouvez simplement développer le modèle avec de nouvelles propriétés et marquer ces propriétés avec le décorateur @jsonIgnore. Et puis ces propriétés ne seront pas sérialisées.
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());