class-transformer

repository·develop·Indexed 27 days ago

https://github.com/typestack/class-transformer

A library for decorator-based transformation, serialization, and deserialization of plain JavaScript objects to class constructors. Version 0.5.1 provides utilities like plainToInstance, instanceToPlain, and decorators such as @Expose, @Exclude, @Type, and @Transform to control how models are mapped, handle nested objects, manage polymorphic types with discriminators, and implement versioning or grouping for API responses.

Tokens
7K
Snippets
20
Records
45
Agent score
91%

What's inside class-transformer

  1. Enforce type-safety by excluding extraneous values

    develop

    By default, plainToInstance sets all properties from the plain object onto the instance, even if they are not defined in the class.

    To prevent this and only allow properties explicitly marked with the @Expose() decorator, use the excludeExtraneousValues: true option in plainToInstance.

    import { Expose, plainToInstance } from 'class-transformer';
    
    class User {
      @Expose() id: number;
      @Expose() firstName: string;
      @Expose() lastName: string;
    }
    
    const fromPlainUser = {
      unkownProp: 'hello there',
      firstName: 'Umed',
      lastName: 'Khudoiberdiev',
    };
    
    // Only id, firstName, and lastName will be present
    const user = plainToInstance(User, fromPlainUser, { excludeExtraneousValues: true });
    import { Expose, plainToInstance } from 'class-transformer';
    
    class User {
      @Expose() id: number;
      @Expose() firstName: string;
      @Expose() lastName: string;
    }
    
    const fromPlainUser = {
      unkownProp: 'hello there',
      firstName: 'Umed',
      lastName: 'Khudoiberdiev',
    };
    
    console.log(plainToInstance(User, fromPlainUser, { excludeExtraneousValues: true }));
    
    // User {
    //   id: undefined,
    //   firstName: 'Umed',
    //   lastName: 'Khudoiberdiev'
    // }
  2. Integrate class-transformer with Angular

    develop

    To map HTTP responses directly to class instances in Angular, use plainToInstance within your observable stream. This ensures that the resulting objects have access to class methods and properties.

    You can also inject ClassTransformer as a service in your Angular providers to access its methods throughout your application.

    import { plainToInstance } from 'class-transformer';
    
    this.http
      .get('users.json')
      .map(res => res.json())
      .map(res => plainToInstance(User, res as Object[]))
      .subscribe(users => {
        // "users" is now type of User[] and has access to User methods
        console.log(users);
      });
  3. Install class-transformer in the Browser

    develop

    To use class-transformer in a browser environment, install the packages via npm and ensure reflect-metadata is loaded in your HTML head.

    1. Install the modules:
      npm install class-transformer --save
      npm install reflect-metadata --save
    2. Add the reflect-metadata script to the <head> of your index.html:
      <head>
        <script src="node_modules/reflect-metadata/Reflect.js"></script>
      </head>
    3. If using SystemJS, add the following to your map and packages configuration:
      {
        "map": {
          "class-transformer": "node_modules/class-transformer"
        },
        "packages": {
          "class-transformer": { "main": "index.js", "defaultExtension": "js" }
        }
      }
    npm install class-transformer --save
    npm install reflect-metadata --save
  4. Install class-transformer in Node.js

    develop

    To use class-transformer in a Node.js environment, install the package and the required reflect-metadata shim. If you are using an older version of Node.js, you may also need es6-shim.

    1. Install the main module and the metadata shim:
      npm install class-transformer --save
      npm install reflect-metadata --save
    2. Import reflect-metadata at a global entry point (e.g., app.ts):
      import 'reflect-metadata';
    3. (Optional) For older Node.js versions, install and import es6-shim:
      npm install es6-shim --save
      import 'es6-shim';
    npm install class-transformer --save
    npm install reflect-metadata --save
  5. Transform a class instance to a plain object

    develop

    Use decorators like @Expose and @Exclude within your class definitions to control how properties are mapped during transformation.

    • @Expose({ name: 'new_name' }): Remaps a property to a different name in the resulting plain object.
    • @Expose(): Explicitly exposes a property.
    • @Exclude(): Prevents a property from being included in the transformed plain object.
    import { Expose, Exclude, classToInstance } from 'class-transformer';
    
    class User {
      /**
       * When transformed to plain the `_id` property will be remapped to `id`
       * in the plain object.
       */
      @Expose({ name: 'id' })
      private _id: string;
    
      /**
       * Expose the `name` property as it is in the plain object.
       */
      @Expose()
      public name: string;
    
      /**
       * Exclude the `passwordHash` so it won't be included in the plain object.
       */
      @Exclude()
      public passwordHash: string;
    }
    
    const user = getUserMagically();
    // contains: User { _id: '42', name: 'John Snow', passwordHash: '2f55ce082...' }
    
    const plain = classToInstance(user);
    // contains { id: '42', name: 'John Snow' }
  6. Transform nested objects using @Type

    develop

    To transform nested objects, you must explicitly specify the target type using the @Type decorator because TypeScript reflection is limited. This ensures that nested plain objects are correctly instantiated as class instances.

    For arrays, you must also use @Type to specify the type of the elements within the array.

    import { Type, plainToInstance } from 'class-transformer';
    
    export class Album {
      id: number;
      name: string;
    
      @Type(() => Photo)
      photos: Photo[];
    }
    
    export class Photo {
      id: number;
      filename: string;
    }
    
    let album = plainToInstance(Album, albumJson);
    // album is now an Album instance containing Photo instances
  7. Control exposure using groups or versioning

    develop

    Using Groups

    Use @Expose({ groups: ['group1', 'group2'] }) to ensure a property is only included when the transformation is performed with one of those groups.

    Using Versioning

    Use @Expose({ since: 0.7, until: 1 }) to control property visibility based on an API version. This is useful for managing breaking changes in evolving APIs.

    import { Exclude, Expose, instanceToPlain } from 'class-transformer';
    
    // Groups
    export class User {
      @Expose({ groups: ['user', 'admin'] })
      email: string;
    
      @Expose({ groups: ['user'] })
      password: string;
    }
    
    // Versioning
    export class User {
      @Expose({ since: 0.7, until: 1 })
      email: string;
    
      @Expose({ since: 2.1 })
      password: string;
    }
    
    // Usage
    let user1 = instanceToPlain(user, { groups: ['user'] });
    let user2 = instanceToPlain(user, { version: 2.1 });
  8. Use transformation decorators on methods

    develop

    You can use decorators on class methods to automatically transform their return values during execution. These decorators accept an optional ClassTransformOptions argument (e.g., groups, version, name).

    Available decorators:

    • @TransformClassToPlain({ groups: [...] }): Transforms the method return using instanceToPlain and exposes the properties on the class.
    • @TransformClassToClass({ groups: [...] }): Transforms the method return using instanceToInstance and exposes the properties on the class.
    • @TransformPlainToClass(TargetClass, { groups: [...] }): Transforms the method return using plainToInstance and exposes the properties on the class.
    @Exclude()
    class User {
      id: number;
    
      @Expose()
      firstName: string;
    
      @Expose()
      lastName: string;
    
      @Expose({ groups: ['user.email'] })
      email: string;
    
      password: string;
    }
    
    class UserController {
      @TransformClassToPlain({ groups: ['user.email'] })
      getUser() {
        const user = new User();
        user.firstName = 'Snir';
        user.lastName = 'Segal';
        user.password = 'imnosuperman';
    
        return user;
      }
    }
    
    const controller = new UserController();
    const user = controller.getUser();
    // user will contain only firstName, lastName, and email properties.
  9. Expose getters, methods, or properties with different names

    develop

    Use the @Expose() decorator to include getters or methods in the transformation. You can also use @Expose({ name: 'new_name' }) to map a property to a different name in the resulting plain object.

    import { Expose } from 'class-transformer';
    
    export class User {
      @Expose({ name: 'uid' })
      id: number;
    
      firstName: string;
      lastName: string;
      password: string;
    
      @Expose()
      get name() {
        return this.firstName + ' ' + this.lastName;
      }
    
      @Expose()
      getFullName() {
        return this.firstName + ' ' + this.lastName;
      }
    }
  10. Deserialize JSON with deserialize and deserializeArray

    develop

    Use deserialize to convert a plain object into a class instance. For arrays of objects, use deserializeArray.

    import { deserialize, deserializeArray } from 'class-transformer';
    
    // For a single object
    let photo = deserialize(Photo, photoJson);
    
    // For an array of objects
    let photos = deserializeArray(Photo, photosJson);
    import { deserialize } from 'class-transformer';
    let photo = deserialize(Photo, photo);
    
    // To make deserialization work with arrays, use the deserializeArray method:
    import { deserializeArray } from 'class-transformer';
    let photos = deserializeArray(Photo, photos);