TypeScript:使用属性的类型验证将JSON反序列化为类

哈Ha! 我想与您分享将JSON对象反序列化为类的库,该库还可以按类型自动验证输入数据。

不久之前,JavaScript中出现了类的奇妙事物,从而大大简化了编写代码的过程。 但不幸的是,没有出现将JSON反序列化为这些相同类的功能,即 您可以将一个类序列化为一个字符串,但可以自己返回。 为了解决此缺陷,我编写了ts可序列化库,希望与您分享。

以下代码显示了问题的实质:

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; //     

新伊凡(Ivan)错误的原因是什么? 事实是JSON.parse方法不会反序列化到User类,而是反序列化到Object类,而Object类根本没有getFullName和getAge方法。

我的库如何帮助解决此问题并在User(而不是Object)中反序列化? 只需稍微修改一下代码就足够了:

 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; //    

一切都非常简单。 我们从Serializable类继承我们的类,该类具有两个用于反序列化的fromJson方法和用于序列化的toJSON,并且使用允许从JSON接受的属性挂起@jsonProperty装饰器。 无效的数据将被忽略,将向控制台发出警告,并且默认值将保留在属性中。

基本上就是这样。 现在在最前面,您可以像使用C#,Java和其他语言一样轻松地反序列化和序列化。 基于Newtonsoft Json.NET的行为。

常见问题


为什么要继承Serializable?

为了向模型添加两个fromJson和toJSON方法。 您可以通过装饰器或猴子修补进行相同的操作。 但是对于Typescript而言,继承是一种更合适的方法。

数据验证如何进行

在装饰器中,您必须分配一个允许从JSON接受的数据类型的构造函数。 布尔,字符串,数字对象将分别返回布尔,字符串,数字。 如果需要接受一个数组,则该类型由数组的方括号括起来,例如@jsonProperty([String])。 如果构造函数是从Serializable类继承的,则它也将反序列化到该类中,否则,将返回该对象。

如何捕捉验证错误?

默认情况下,该库仅向控制台写入有关验证错误的警告。 要覆盖此行为(例如引发异常或记录到后端),必须覆盖模型的onWrongType方法。

奖金1.深复制。


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

奖励2.懒惰的ViewModels。


如果您需要使用其他数据(例如,用于视图的数据)创建模型,但后端不接受,则可以简单地使用新属性扩展模型,并使用@jsonIgnore装饰器标记这些属性。 然后这些属性将不会被序列化。

 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/zh-CN428812/


All Articles