如何创建简单的Typescript元数据注释

时间:2016-06-28 20:39:52

标签: json serialization typescript angular decorator

我有一些字段需要在发送到服务器端之前进行格式化。

所以,我想使用自定义序列化程序序列化我的typescript类的一些字段,这样的理想选择:

export class Person {
    @serializeWith(MyDateSerializer)
    private date: Date;
}

post(url, value) {
    this.http.post(url, JSON.stringfy(value, (key, val) => {
       if (//value has serializeWith annotation) {
           return //serialize with custom serializer
       }
    }));
}

接近这一点是可以接受的,欢迎任何帮助。 感谢

1 个答案:

答案 0 :(得分:21)

我的解决方案建立在以下基础之上:

  1. TypeScript Decorators
  2. Metadata spec (early stage/experimental)
  3. 先决条件:

    1. tsconfig.json或命令行中的TypeScript中启用装饰器和装饰器元数据支持:
    2. <强> tsconfig.json

      {
          "compilerOptions": {
              "target": "es5", // you have to target es5+
              "experimentalDecorators": true,
              "emitDecoratorMetadata": true
              // ....
          }
          // ...
      }
      
      1. 安装reflect-metadata

        npm install --save-dev reflect-metadata

      2. serializerWith装饰者(工厂)

        装饰器工厂需要一个或多个参数,并返回TypeScript在生成的JavaScript代码中使用的装饰器函数。

        我选择直接将序列化函数传递到我的装饰器工厂,并使用metdata规范的reflect-metadata实现将序列化器函数与属性相关联。我稍后会检索它并在运行时使用它。

        function serializeWith(serializer: (input: any) => string) : (target: any, propertyKey: string) => void {
            return function(target: any, propertyKey: string) {
                // serialization here is the metadata key (something like a category)
                Reflect.defineMetadata("serialization", serializer, target, propertyKey);
            }
        }
        

        使用

        鉴于此序列化器:

        function MyDateSerializer(value : any) : string {
            console.log("MyDateSerializer called");
            return "dummy value";
        }
        

        然后我们可以像这样应用装饰工厂:

        import "reflect-metadata"; // has to be imported before any decorator which uses it is applied
        
        class Greeter {
            @serializeWith(MyDateSerializer)
            public greeting : string;
        
            constructor(message: string) {
                this.greeting = message;
            }
        }
        

        我们可以像这样使用序列化器:

        var greetingInstance = new Greeter("hi");
        
        var serializerFunc : (input: any) => string = Reflect.getMetadata("serialization", greetingInstance, "greeting");
        
        serializerFunc(greetingInstance.greeting);
        

        样品

        <强> main.ts

        import "reflect-metadata";
        
        function serializeWith(serializer: (input: any) => string) : (target: any, propertyKey: string) => void {
            return function(target: any, propertyKey: string) {
                console.log("serializeWith called: adding metadata");
                Reflect.defineMetadata("serialization", serializer, target, propertyKey);
            }
        }
        
        
        function MyDateSerializer(value : any) : string {
            console.log("MyDateSerializer called");
            return "bla";
        }
        
        class Greeter {
            @serializeWith(MyDateSerializer)
            public greeting : string;
        
            constructor(message: string) {
                console.log("Greeter constructor");
                this.greeting = message;
            }
        }
        
        var greetingInstance = new Greeter("hi");
        
        var serializerFunc : (input: any) => string = Reflect.getMetadata("serialization", greetingInstance, "greeting");
        
        var serializedValue = serializerFunc(greetingInstance.greeting);
        console.log(serializedValue);
        

        <强>输出

        c:\code\tmp\lll>node build\main.js
        serializeWith called: adding metadata
        Greeter constructor
        MyDateSerializer called
        bla
        
相关问题