Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

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

Decorator-based transformation, serialization, and deserialization between objects and classes.
https://github.com/typestack/class-transformer

exposing-getters exposing-properties transformation typescript

Last synced: 6 days ago
JSON representation

Decorator-based transformation, serialization, and deserialization between objects and classes.

Awesome Lists containing this project

README

        

# class-transformer

![Build Status](https://github.com/typestack/class-transformer/workflows/CI/badge.svg)
[![codecov](https://codecov.io/gh/typestack/class-transformer/branch/develop/graph/badge.svg)](https://codecov.io/gh/typestack/class-transformer)
[![npm version](https://badge.fury.io/js/class-transformer.svg)](https://badge.fury.io/js/class-transformer)

Its ES6 and Typescript era. Nowadays you are working with classes and constructor objects more than ever.
Class-transformer allows you to transform plain object to some instance of class and versa.
Also it allows to serialize / deserialize object based on criteria.
This tool is super useful on both frontend and backend.

Example how to use with angular 2 in [plunker](http://plnkr.co/edit/Mja1ZYAjVySWASMHVB9R).
Source code is available [here](https://github.com/pleerock/class-transformer-demo).

## Table of contents

- [What is class-transformer](#what-is-class-transformer)
- [Installation](#installation)
- [Node.js](#nodejs)
- [Browser](#browser)
- [Methods](#methods)
- [plainToInstance](#plaintoinstance)
- [plainToClassFromExist](#plaintoclassfromexist)
- [instanceToPlain](#instancetoplain)
- [instanceToInstance](#instanceToInstance)
- [serialize](#serialize)
- [deserialize and deserializeArray](#deserialize-and-deserializearray)
- [Enforcing type-safe instance](#enforcing-type-safe-instance)
- [Working with nested objects](#working-with-nested-objects)
- [Providing more than one type option](#providing-more-than-one-type-option)
- [Exposing getters and method return values](#exposing-getters-and-method-return-values)
- [Exposing properties with different names](#exposing-properties-with-different-names)
- [Skipping specific properties](#skipping-specific-properties)
- [Skipping depend of operation](#skipping-depend-of-operation)
- [Skipping all properties of the class](#skipping-all-properties-of-the-class)
- [Skipping private properties, or some prefixed properties](#skipping-private-properties-or-some-prefixed-properties)
- [Using groups to control excluded properties](#using-groups-to-control-excluded-properties)
- [Using versioning to control exposed and excluded properties](#using-versioning-to-control-exposed-and-excluded-properties)
- [Сonverting date strings into Date objects](#сonverting-date-strings-into-date-objects)
- [Working with arrays](#working-with-arrays)
- [Additional data transformation](#additional-data-transformation)
- [Basic usage](#basic-usage)
- [Advanced usage](#advanced-usage)
- [Other decorators](#other-decorators)
- [Working with generics](#working-with-generics)
- [Implicit type conversion](#implicit-type-conversion)
- [How does it handle circular references?](#how-does-it-handle-circular-references)
- [Example with Angular2](#example-with-angular2)
- [Samples](#samples)
- [Release notes](#release-notes)

## What is class-transformer[⬆](#table-of-contents)

In JavaScript there are two types of objects:

- plain (literal) objects
- class (constructor) objects

Plain objects are objects that are instances of `Object` class.
Sometimes they are called **literal** objects, when created via `{}` notation.
Class objects are instances of classes with own defined constructor, properties and methods.
Usually you define them via `class` notation.

So, what is the problem?

Sometimes you want to transform plain javascript object to the ES6 **classes** you have.
For example, if you are loading a json from your backend, some api or from a json file,
and after you `JSON.parse` it you have a plain javascript object, not instance of class you have.

For example you have a list of users in your `users.json` that you are loading:

```json
[
{
"id": 1,
"firstName": "Johny",
"lastName": "Cage",
"age": 27
},
{
"id": 2,
"firstName": "Ismoil",
"lastName": "Somoni",
"age": 50
},
{
"id": 3,
"firstName": "Luke",
"lastName": "Dacascos",
"age": 12
}
]
```

And you have a `User` class:

```typescript
export class User {
id: number;
firstName: string;
lastName: string;
age: number;

getName() {
return this.firstName + ' ' + this.lastName;
}

isAdult() {
return this.age > 36 && this.age < 60;
}
}
```

You are assuming that you are downloading users of type `User` from `users.json` file and may want to write
following code:

```typescript
fetch('users.json').then((users: User[]) => {
// you can use users here, and type hinting also will be available to you,
// but users are not actually instances of User class
// this means that you can't use methods of User class
});
```

In this code you can use `users[0].id`, you can also use `users[0].firstName` and `users[0].lastName`.
However you cannot use `users[0].getName()` or `users[0].isAdult()` because "users" actually is
array of plain javascript objects, not instances of User object.
You actually lied to compiler when you said that its `users: User[]`.

So what to do? How to make a `users` array of instances of `User` objects instead of plain javascript objects?
Solution is to create new instances of User object and manually copy all properties to new objects.
But things may go wrong very fast once you have a more complex object hierarchy.

Alternatives? Yes, you can use class-transformer. Purpose of this library is to help you to map your plain javascript
objects to the instances of classes you have.

This library also great for models exposed in your APIs,
because it provides a great tooling to control what your models are exposing in your API.
Here is an example how it will look like:

```typescript
fetch('users.json').then((users: Object[]) => {
const realUsers = plainToInstance(User, users);
// now each user in realUsers is an instance of User class
});
```

Now you can use `users[0].getName()` and `users[0].isAdult()` methods.

## Installation[⬆](#table-of-contents)

### Node.js[⬆](#table-of-contents)

1. Install module:

`npm install class-transformer --save`

2. `reflect-metadata` shim is required, install it too:

`npm install reflect-metadata --save`

and make sure to import it in a global place, like app.ts:

```typescript
import 'reflect-metadata';
```

3. ES6 features are used, if you are using old version of node.js you may need to install es6-shim:

`npm install es6-shim --save`

and import it in a global place like app.ts:

```typescript
import 'es6-shim';
```

### Browser[⬆](#table-of-contents)

1. Install module:

`npm install class-transformer --save`

2. `reflect-metadata` shim is required, install it too:

`npm install reflect-metadata --save`

add `` to reflect-metadata in the head of your `index.html`:

```html
<html>
<head>
<!-- ... -->
<script src="node_modules/reflect-metadata/Reflect.js">