fontcolor_theme
Deepkit Runtime Types

カスタムシリアライザ

デフォルトでは、@deepkit/type には JSON シリアライザと TypeScript の型検証が付属しています。これを拡張してシリアライズ機能を追加・削除したり、検証の方法を変更することができます。検証はシリアライザとも連動しています。

新しいシリアライザ

シリアライザは、シリアライザ テンプレートが登録された Serializer Class の単なるインスタンスです。シリアライザ テンプレートは、JIT シリアライザ処理のための JavaScript コードを生成する小さな Function です。各型(String、Number、Boolean など)ごとに、データ変換や検証のためのコードを返す専用のシリアライザ テンプレートが用意されます。このコードは、ユーザーが使用している JavaScript エンジンと互換である必要があります。

コンパイラ テンプレート関数の実行時にのみ、完全な型情報に(もしくはそうあるべきように)フルアクセスできます。型を変換するために必要な情報をすべて直接 JavaScript コードに埋め込むことで、高度に最適化されたコード(JIT 最適化コードとも呼ばれます)を得る、というのが狙いです。

次の例では空のシリアライザを作成します。

import { EmptySerializer } from '@deepkit/type';

class User {
    name: string = '';
    created: Date = new Date;
}

const mySerializer = new EmptySerializer('mySerializer');

const user = deserialize<User>({ name: 'Peter', created: 0 }, undefined, mySerializer);
console.log(user);
$ ts-node app.ts
User { name: 'Peter', created: 0 }

ご覧の通り、何も変換されていません(created は依然として数値ですが、Date として定義しています)。これを変更するため、Date 型のデシリアライズ用シリアライザ テンプレートを追加します。

mySerializer.deserializeRegistry.registerClass(Date, (type, state) => {
    state.addSetter(`new Date(${state.accessor})`);
});

const user = deserialize<User>({ name: 'Peter', created: 0 }, undefined, mySerializer);
console.log(user);
$ ts-node app.ts
User { name: 'Peter', created: 2021-06-10T19:34:27.301Z }

これでシリアライザは値を Date オブジェクトに変換します。

シリアライズでも同様にするため、別のシリアライズ用テンプレートを登録します。

mySerializer.serializeRegistry.registerClass(Date, (type, state) => {
    state.addSetter(`${state.accessor}.toJSON()`);
});

const user1 = new User();
user1.name = 'Peter';
user1.created = new Date('2021-06-10T19:34:27.301Z');
console.log(serialize(user1, undefined, mySerializer));
{ name: 'Peter', created: '2021-06-10T19:34:27.301Z' }

新しいシリアライザは、シリアライズ処理で Date オブジェクトの日付を文字列に正しく変換します。

さらに多くの例については、Deepkit Type に含まれている JSON シリアライザ のコードを参照してください。

既存のシリアライザの拡張

既存のシリアライザを拡張したい場合は、Class 継承を使って実現できます。これは、シリアライザが constructor でテンプレートを登録するように作られているため機能します。

class MySerializer extends Serializer {
    constructor(name: string = 'mySerializer') {
        super(name);
        this.registerTemplates();
    }

    protected registerTemplates() {
        this.deserializeRegistry.register(ReflectionKind.string, (type, state) => {
            state.addSetter(`String(${state.accessor})`);
        });

        this.deserializeRegistry.registerClass(Date, (type, state) => {
            state.addSetter(`new Date(${state.accessor})`);
        });

        this.serializeRegistry.registerClass(Date, (type, state) => {
            state.addSetter(`${state.accessor}.toJSON()`);
        });
    }
}
const mySerializer = new MySerializer();
English中文 (Chinese)한국어 (Korean)日本語 (Japanese)Deutsch (German)