TypeScript:プロパティの型検証を使用してJSONをクラスに逆シリアル化する

こんにちは、Habr! JSONオブジェクトをクラスにデシリアライズするためのライブラリを共有したいと思います。クラスは入力データをタイプごとに自動的に検証します。



少し前までは、クラスがJavaScriptに登場したようなすばらしいことが、コードの記述プロセスを大幅に簡素化しました。 しかし、残念ながら、JSONをこれらの同じクラスに逆シリアル化する機能は表示されませんでした。 クラスを文字列にシリアル化できますが、独自に戻すことができます。 そして、この欠点を修正するために、 ts-serializableライブラリが作成されました。これを共有します。



問題の本質は、次のコードで示されています。



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





新しいイワンの間違いの原因は何ですか? 実際には、JSON.parseメソッドはUserクラスではなく、単にgetFullNameメソッドとgetAgeメソッドを持たない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; //   
      
      





すべてが非常に簡単です。 デシリアライゼーション用のfromJsonメソッドとシリアライゼーション用のtoJSONの2つのメソッドを持つSerializableクラスからクラスを継承し、JSONから受け入れることができるプロパティで@jsonPropertyデコレータを切断します。 無効なデータは無視され、警告がコンソールに発行され、デフォルト値がプロパティに残ります。



それは基本的にそれです。 これで、前面で、C#、Java、および他の言語で行うのと同じくらい簡単に逆シリアル化およびシリアル化できます。 Newtonsoft Json.NETの動作に基づいています。



よくある質問



Serializableから継承する理由



2つのfromJsonおよびtoJSONメソッドをモデルに追加するため。 デコレータまたはモンキーパッチングでも同じことができます。 しかし、継承はTypescriptにとってより適切な方法です。



データ検証の方法



デコレーターでは、JSONから受け入れられるデータ型のコンストラクターを割り当てる必要があります。 ブール、ストリング、数値オブジェクトは、それぞれブール、ストリング、数値を返します。 配列を受け入れる必要がある場合、型は配列の角括弧で囲まれます(@jsonProperty([String])など)。 コンストラクターがSerializableクラスから継承される場合、コンストラクターもクラスに逆シリアル化されます。継承されない場合、オブジェクトが返されます。



検証エラーをキャッチする方法は?



デフォルトでは、ライブラリは検証エラーに関する警告をコンソールに書き込むだけです。 例外のスローやバックエンドへのログ記録など、この動作をオーバーライドするには、モデルのonWrongTypeメソッドをオーバーライドする必要があります。



ボーナス1.ディープコピー。



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





ボーナス2。遅延モデル。



ビューなどの追加データを使用してモデルを作成する必要があるが、バックエンドがそれを受け入れない場合、新しいプロパティでモデルを展開し、@ 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":""}
      
      






All Articles