Coder Social home page Coder Social logo

typestack / class-transformer Goto Github PK

View Code? Open in Web Editor NEW
6.5K 40.0 474.0 3.12 MB

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

License: MIT License

JavaScript 0.36% TypeScript 99.64%
typescript transformation exposing-properties exposing-getters

class-transformer's People

Contributors

artemln avatar ballomud avatar cojack avatar cvlvxi avatar dependabot[bot] avatar driccio avatar jotamorais avatar leon19 avatar lucas-gregoire avatar mateusgrb avatar maxint137 avatar mtschannett avatar nadavk avatar nimaen avatar nonameprovided avatar nouc23 avatar pahuta avatar pleerock avatar rasmussyberg avatar rishabhrpg avatar rmuchall avatar saulotoledo avatar sheiidan avatar snirs90 avatar sparebytes avatar strictd avatar tbreug avatar tmtron avatar velmisov avatar willemmulder avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

class-transformer's Issues

Cannot read property 'defaultMetadataStorage' of undefined

Im using your package in an Ionic2 / Angular2 project. Since the upgrade to the latest RC version of Ionic, where rollup.js is used as a build system, I get the following error:

error_handler.js:51 TypeError: Cannot read property 'defaultMetadataStorage' of undefined
  at TransformOperationExecutor.getKeys (TransformOperationExecutor.js:219)
  at TransformOperationExecutor.transform (TransformOperationExecutor.js:68)
  at ClassTransformer.plainToClass (ClassTransformer.js:16)
  at plainToClass (index.js:20)

Now, probability us great, that the build process is causing the problem. But if someone has an idea on how to solve this - please do not hesitate ;-)

Is there support for json-api

Hi,

Just tried your library with an Angular2 project and it works perfectly with my json-server testdata :-)

However. We're using a Rails backend and are planning on using json-api, would it be possible to use your library with a json file like this or would that be really hard/complex?

{
  "links": {
    "self": "http://example.com/articles",
    "next": "http://example.com/articles?page[offset]=2",
    "last": "http://example.com/articles?page[offset]=10"
  },
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON API paints my bikeshed!"
    },
    "relationships": {
      "author": {
        "links": {
          "self": "http://example.com/articles/1/relationships/author",
          "related": "http://example.com/articles/1/author"
        },
        "data": { "type": "people", "id": "9" }
      },
      "comments": {
        "links": {
          "self": "http://example.com/articles/1/relationships/comments",
          "related": "http://example.com/articles/1/comments"
        },
        "data": [
          { "type": "comments", "id": "5" },
          { "type": "comments", "id": "12" }
        ]
      }
    },
    "links": {
      "self": "http://example.com/articles/1"
    }
  }],
  "included": [{
    "type": "people",
    "id": "9",
    "attributes": {
      "first-name": "Dan",
      "last-name": "Gebhardt",
      "twitter": "dgeb"
    },
    "links": {
      "self": "http://example.com/people/9"
    }
  }, {
    "type": "comments",
    "id": "5",
    "attributes": {
      "body": "First!"
    },
    "relationships": {
      "author": {
        "data": { "type": "people", "id": "2" }
      }
    },
    "links": {
      "self": "http://example.com/comments/5"
    }
  }, {
    "type": "comments",
    "id": "12",
    "attributes": {
      "body": "I like XML better"
    },
    "relationships": {
      "author": {
        "data": { "type": "people", "id": "9" }
      }
    },
    "links": {
      "self": "http://example.com/comments/12"
    }
  }]
}

Nested keys don't work as expected

Hi,

Here's a simple example that I expected to work:

import { plainToClass, Expose } from 'class-transformer';

let personObj = {
    first_name: 'Joseph', 
    last_name: 'Maxwell',
    aka: {
        nick_name: 'Joe'
    }
}

export class Person {
    @Expose({ name: 'first_name' })
    firstname: string;

    @Expose({ name: 'last_name' })
    lastname: string;

    @Expose({ name: 'aka.nick_name' })
    nickname: string;
}

let person: Person = plainToClass(Person, personObj);

person.firstname = 'Joseph'ย ย ย ย :heavy_check_mark:
person.lastname = 'Maxwell'ย ย ย ย :heavy_check_mark:
person.nickname = undefinedย ย ย ย :x: // Why? I want the value in personObj.aka.nick_name
person.aka.nick_name = 'Joe'ย ย :x: // Why is this here?

What am I doing wrong?

TypeError: newValue_1.push is not a function

Hello,
I get the following error whenever I try to plainToClass from json:

TypeError: newValue_1.push is not a function
at http://localhost:4200/vendor.bundle.js:92475:36
at Array.forEach (native)
at TransformOperationExecutor.transform (http://localhost:4200/vendor.bundle.js:92467:19)
at _loop_1 (http://localhost:4200/vendor.bundle.js:92590:45)
at TransformOperationExecutor.transform (http://localhost:4200/vendor.bundle.js:92613:17)
at http://localhost:4200/vendor.bundle.js:92470:41
at Array.forEach (native)
at TransformOperationExecutor.transform (http://localhost:4200/vendor.bundle.js:92467:19)
at _loop_1 (http://localhost:4200/vendor.bundle.js:92590:45)
at TransformOperationExecutor.transform (http://localhost:4200/vendor.bundle.js:92613:17)
at ClassTransformer.plainToClass (http://localhost:4200/vendor.bundle.js:50796:25)
at plainToClass (http://localhost:4200/vendor.bundle.js:7507:29)
at MapSubscriber.project (http://localhost:4200/main.bundle.js:1547:128)
at MapSubscriber._next (http://localhost:4200/vendor.bundle.js:15533:35)
at MapSubscriber.Subscriber.next (http://localhost:4200/vendor.bundle.js:488:18)

This is the json:

{
"id": 1,
"tipo": "O",
"descrizione": "Menu Produzione",
"posizione": 1,
"nota": "",
"menuRaggruppamenti": [
{
"id": 1,
"menuId": 1,
"descrizione": "Anagrafiche",
"descrizioneCorta": "Anagrafiche",
"posizione": 1,
"nota": "",
"menuModuli": [
{
"id": 1,
"raggruppamentoId": 1,
"descrizione": "Sviluppo Collezione Prodotto",
"descrizioneCorta": "SPC",
"posizione": 1,
"nota": "",
"moduloDefault": 0
},
{
"id": 2,
"raggruppamentoId": 1,
"descrizione": "Configuratore Componenti",
"descrizioneCorta": "Componenti",
"posizione": 2,
"nota": "",
"moduloDefault": 0
}
]
},
{
"id": 2,
"menuId": 1,
"descrizione": "Tabelle",
"descrizioneCorta": "Tabelle",
"posizione": 2,
"nota": "",
"menuModuli": [
{
"id": 4,
"raggruppamentoId": 2,
"descrizione": "Collezioni",
"descrizioneCorta": "Collezioni",
"posizione": 1,
"nota": "",
"moduloDefault": 0
},
{
"id": 3,
"raggruppamentoId": 2,
"descrizione": "Contatti",
"descrizioneCorta": "Contatti",
"posizione": 2,
"nota": "",
"moduloDefault": 0
},
{
"id": 17,
"raggruppamentoId": 2,
"descrizione": "Forme",
"descrizioneCorta": "Forme",
"posizione": 3,
"nota": "",
"moduloDefault": 0
},
{
"id": 5,
"raggruppamentoId": 2,
"descrizione": "Fornitori",
"descrizioneCorta": "Fornitori",
"posizione": 4,
"nota": "",
"moduloDefault": 0
},
{
"id": 6,
"raggruppamentoId": 2,
"descrizione": "Materiali",
"descrizioneCorta": "Materiali",
"posizione": 5,
"nota": "",
"moduloDefault": 0
}
]
},
{
"id": 3,
"menuId": 1,
"descrizione": "Reportistica",
"descrizioneCorta": "Reportistica",
"posizione": 3,
"nota": "",
"menuModuli": [
{
"id": 8,
"raggruppamentoId": 3,
"descrizione": "Controllo Avanzamento Linea",
"descrizioneCorta": "Avanzamento",
"posizione": 1,
"nota": "",
"moduloDefault": 0
},
{
"id": 9,
"raggruppamentoId": 3,
"descrizione": "Monitor Collezione",
"descrizioneCorta": "Monitor",
"posizione": 2,
"nota": "",
"moduloDefault": 1
}
]
}
]
}

It comes from a http call, this is the code:

    return this.http.authget(url)
        .map(response => <Menu>response.json())            
        .map(res => plainToClass(Menu, res as Object))
        .catch(this.handleError);

And these are the models:

import { MenuRaggruppamento } from "./menuraggruppamento";
import { Type, plainToClass } from "class-transformer";

export class Menu {

public id: number;
public tipo: string;
public descrizione: string;
public posizione: number;
public nota: string;
@Type(() => MenuRaggruppamento)
public menuRaggruppamenti: Array<MenuRaggruppamento>;

constructor() {
    this.id = 0;
    this.tipo = "";
    this.descrizione = "";
    this.posizione = 0;
    this.nota = "";
    this.menuRaggruppamenti = [];
}

}

import { MenuModulo } from "./menumodulo";
import { Type, plainToClass } from "class-transformer";

export class MenuRaggruppamento {

public id: number;
public menuId: number;
public descrizione: string;
public descrizioneCorta: string;
public posizione: number;
public nota: string;
@Type(() => MenuModulo)
public menuModuli: Array<MenuModulo>;

constructor() {
    this.id = 0;
    this.menuId = 0;
    this.descrizione = "";
    this.descrizioneCorta = "";
    this.posizione = 0;
    this.nota = "";
    this.menuModuli = [];
}

}

export class MenuModulo {

public id: number;
public raggruppamentoId: number;
public codice: string;
public descrizione: string;
public descrizioneCorta: string;
public posizione: number;
public nota: string;
public moduloDefault: boolean;

constructor(
) {
    this.id = 0;
    this.raggruppamentoId = 0;
    this.codice = "";
    this.descrizione = "";
    this.descrizioneCorta = "";
    this.posizione = 0;
    this.nota = "";
    this.moduloDefault = false;
}

}

My project has been created with Angular cli 1.0.0-beta.26, Angular 2.4.5

That's my package json:

{
"name": "gea-collection",
"version": "1.0.0",
"license": "MIT",
"angular-cli": {},
"scripts": {
"ng": "ng",
"start": "ng serve --proxy-config proxy.conf.json --open true",
"lint": "tslint "src//*.ts" --project src/tsconfig.json --type-check && tslint "e2e//*.ts" --project e2e/tsconfig.json --type-check",
"test": "ng test",
"pree2e": "webdriver-manager update --standalone false --gecko false",
"e2e": "protractor"
},
"private": true,
"dependencies": {
"@angular/common": "^2.4.5",
"@angular/compiler": "^2.4.5",
"@angular/core": "^2.4.5",
"@angular/forms": "^2.4.5",
"@angular/http": "^2.4.5",
"@angular/platform-browser": "^2.4.5",
"@angular/platform-browser-dynamic": "^2.4.5",
"@angular/router": "^3.4.5",
"@angular/upgrade": "^2.4.5",
"bootstrap": "^3.3.7",
"class-transformer": "^0.1.6",
"core-js": "^2.4.1",
"ng2-bootstrap": "^1.3.1",
"primeng": "^1.1.4",
"reflect-metadata": "^0.1.9",
"rxjs": "^5.0.3",
"typings": "^2.1.0",
"zone.js": "^0.7.6"
},
"devDependencies": {
"@angular/compiler-cli": "^2.4.5",
"@types/node": "^7.0.4",
"angular-cli": "^1.0.0-beta.26",
"codelyzer": "^2.0.0-beta.4",
"font-awesome": "^4.7.0",
"jasmine-core": "2.5.2",
"jasmine-spec-reporter": "2.5.0",
"karma": "1.2.0",
"karma-chrome-launcher": "^2.0.0",
"karma-cli": "^1.0.1",
"karma-jasmine": "^1.0.2",
"karma-remap-istanbul": "^0.2.1",
"protractor": "^5.0.0",
"ts-node": "^2.0.0",
"tslint": "^4.4.2",
"typescript": "^2.1.4"
}
}

Any idea?
Thank you
Giovanni

Ignore extra properties when creating instance from plain object

Hello!

Please consider a use case where we are converting plain object to class object using plainToClass() and plain object has more properties than class supports, i.e. it contains extra ones. In current implementation, those properties are added to the newly created instance. However, I would like to avoid that.

Is there a way to disable adding of extra properties? Globally switch is preferred.

The only workaround I've found is to add @Exclude() to the entire class and then to @Expose each property manually. With this approach extra properties are ignored, but it could be tiresome to configure and readability is also suffer.

Thanks!

plainToConstructor convert Date to ISO string

If the datatype of a plain json was already a date object, plainToConstructor will convert it to ISO String.

export class A {
    @Type(()=>Date)
    somedate:Date = new Date();
}

let json = {
    somedate: new Date()
};

let a = plainToConstructor(A, json);
console.log(a.somedate.constructor.name); // print String

feature: onSerialized/onDeserialized callbacks

I need this feature to initialize the serialized data. Would be nice to have access to the class instance or the plain object in these callbacks, though just the callback with no parameters will suffice in my case.

TypeError: Cannot read property 'prototype' of undefined

I am having three classes Person, BasicDetails and CloudResponse, when I extend BasicDetails class in Person class and then I run the following code it gives me error.

return this.http.post(Environment.domain, JSON.stringify(requestObj), {headers: this.headers})
      .map((res: Response) => {
        return res.json();
      })
      .map(res => plainToClass(MeraCRMCloudResponse, res as Object))
      .catch((error: any) => Observable.throw(console.log(error)));

TypeError: Cannot read property 'prototype' of undefined
at http://localhost:4200/main.bundle.js:60194:84
at Array.filter (native)
at MetadataStorage.findMetadatas (http://localhost:4200/main.bundle.js:60194:46)
at MetadataStorage.findTransformMetadatas (http://localhost:4200/main.bundle.js:60098:21)
at TransformOperationExecutor.applyCustomTransformations (http://localhost:4200/main.bundle.js:59887:58)
at _loop_1 (http://localhost:4200/main.bundle.js:59854:41)
at TransformOperationExecutor.transform (http://localhost:4200/main.bundle.js:59876:31)
at http://localhost:4200/main.bundle.js:59736:41
at Array.forEach (native)
at TransformOperationExecutor.transform (http://localhost:4200/main.bundle.js:59733:19)

Is it possible to map a property to a different name?

Looking at the source and previous issues, I'm pretty confident it's not possible to do the following without manually manipulating my input beforehand.

class Person {
  firstName: string;
}

let data = {
  first_name: 'foo'
};

let person = plainToClass(Person, data);

console.log(person.firstName == 'foo')

I'm aware of the Expose decorator, but that only appears to be used when going from a class to JSON.

fix: problem with convert array

I try to parse:

req.body

Array[3] [Object, Object, Object]
length:3
__proto__:Array[0] []
0:Object {name: "d", _id: "7GJ6aZ9Dkn12o1SF"}
_id:"7GJ6aZ9Dkn12o1SF"
name:"d"
__proto__:Object {}
1:Object {name: "a", _id: "A1iW9VANqYQwu7W8"}
2:Object {name: "b", _id: "MakAun7n55w0zKvw"}
3:Object {name: "c", _id: "dGmgFSl8LvkblxM2"}

but i got:

Array[4] [Array[0], Array[0], Array[0], Array[0]]
length:4
__proto__:Array[0] []
0:Array[0] []
_id:"7GJ6aZ9Dkn12o1SF"
length:0
name:"d"
__proto__:Array[0] []

what wrong?

@Transform - add option to skip the circular check

Hello,
I am using data transformations to avoid circular references by storing an id reference of the object, rather than the object itself.
But class-transformer adds the object to transformedTypes and by the time it has to be serialized, rather than just referenced - it is skipped because isCircular returns true.

Maybe a skipCircularCheck option can be added to @Transform:
@Transform(value => value.id, { toPlainOnly: true, skipCircularCheck:true })

I think this is a common use case - I quite often need to serialize data that contains multiple/circular references to the same object.

Using @Type with v 0.0.6 throws a crypto not found error

After installing serializer.ts v0.0.6 and using the @type decorator I keep getting the following error:
localhost/:99 Error: Error: XHR error (404 Not Found) loading http://localhost:5555/node_modules/crypto/package.json(โ€ฆ)

import {Type} from 'serializer.ts/Decorators';

export class Invoice {
  @Type(() => Number)
  id: number;
}

feat: no property missing & type check in plain object

When you receive from web client a JSON with user credentials and want to use it in login procedure (check in database), you use let user = plainToClass(User, userJson). The problem is that this function doesn't inform you (throw Error or sth) that the class property is missing in json. So you assert like in let user = JSON.parse(userJson) as User and might have undefined login or password.

It would be nice to have an field in function option (interface ClassTransformOptions) like throwErrorIfMissing: true or have decorators @Required or @Optional with different error strategy.
It could throw Error with message "Parsing error: property ${propertyName} is missing." which could be used in response JSON to REST API client.

The other problem is that doesn't check type of object property - you can have filename: true in photo JSON and you will get runtime error when try to use photo.filename as string. And it also copy everything from the plain object, but it's not as dangerous like the the above-mentioned.

You can see how it's all implemented in TypedJSON and when it throws error.

deserialize Expose not working with inheritance in the typescript class.

I am using the class-transformer package to transform the JSON object to typescript class object which is working as expected. But when my typescript class in inherited/extends from some base class then the conversion of JSON to Typescript on base class property is not working.

Here is the sample code-
export class UserBase {
@expose({ name: "payment" })
salary: number;
}

export class User extends UserBase {
@expose({ name: "MyName" })
firstName: string;
lastName: string;
age: number;
}
let jsonuser = { "age": 123, "MyName": "TEST", "lastName": "TESTLastName","payment": 1000 },

if I do deserialize(User, JSON.stringify(jsonuser)); the salary property is not get set , is get as payment only.

Please let me know if I am missing anything here.

Decorator Metadata missing after transpiling

Hi,

I have a package A which defines classes and uses class-transformer decorators.
When I test the package and use classToPlain, the decorators are used and I get my custom transforms and everything as expected.

Then I transpile this package with tsc, and import this package in package B.
When in package B I used classToPlain the decorator metadata is missing. I actually debugged it and saw that metadata is empty. Although I do see the __decorate and __metadata in the transpiled code (The js code).

I made sure that in package B:

  • installed class-transformer
  • installed 'reflect-metadata` and require in global place before everything
  • added to tsconfig.json this "experimentalDecorators": true (although I think it is not necessary if I don't use new decorators, just the ones from package A)

Notes:

  • I am using ts-node/register in my mocha tests in package B
  • Using typescript 2.1.4

Typo in 'ะกonverting date strings into Date objects'

Hi,

I think there is a typo in the section 'ะกonverting date strings into Date objects', it should be

import {Type} from "class-transformer";

export class User {

    id: number;

    email: string;

    password: string;

    @Type(() => Date) //typo here
    registrationDate: Date;
}

First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.

Hello,

My code

public async findOne<T>(cls: ClassType<T>, query:any): Promise<T> {
    let collectionName = Reflect.getMetadata('collectionName', cls);
    let collection = this.mongo.collection(collectionName);
    let json: {} = await collection.findOne(query); // -> returns plain js object
    if(json === null) return null;
    return plainToClass(cls, json);
}

When i use this, it works just fine

    return deserialize(cls, JSON.stringify(json));

Error

TypeError: First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.
    at fromObject (buffer.js:274:9)
    at Function.Buffer.from (buffer.js:106:10)
    at new Buffer (buffer.js:85:17)
    at TransformOperationExecutor.transform (/home/yan/Workspace/typex/node_modules/class-transformer/TransformOperationExecutor.js:77:32)
    at _loop_1 (/home/yan/Workspace/typex/node_modules/class-transformer/TransformOperationExecutor.js:146:45)
    at TransformOperationExecutor.transform (/home/yan/Workspace/typex/node_modules/class-transformer/TransformOperationExecutor.js:169:17)
    at _loop_1 (/home/yan/Workspace/typex/node_modules/class-transformer/TransformOperationExecutor.js:146:45)
    at TransformOperationExecutor.transform (/home/yan/Workspace/typex/node_modules/class-transformer/TransformOperationExecutor.js:169:17)
    at /home/yan/Workspace/typex/node_modules/class-transformer/TransformOperationExecutor.js:26:41
    at Array.forEach (native)

Is this bug or am i doing something wrong.

plainToClass conversion throwing TypeError: newValue_1.push is not a function

I am using Angular2 and while converting my jSon to object facing the error
Uncaught TypeError: newValue_1.push is not a function
at http://localhost:4200/vendor.bundle.js:105285:36
at Array.forEach (native)
at TransformOperationExecutor.transform (http://localhost:4200/vendor.bundle.js:105277:19)
at _loop_1 (http://localhost:4200/vendor.bundle.js:105400:45)
at TransformOperationExecutor.transform (http://localhost:4200/vendor.bundle.js:105423:17)
at http://localhost:4200/vendor.bundle.js:105280:41

The JSON I am using is :
[{
"name": "LegalStructure",
"id": 1,
"values": [{
"id": 2,
"name": "Besloten Vennootschap"
}, {
"id": 3,
"name": "Naamloze Vennootschap"
}]
}, {
"name": "AddressType",
"id": 9,
"values": [{
"id": 10,
"name": "Registered Address"
}, {
"id": 11,
"name": "Office Address"
}, {
"id": 12,
"name": "Home Address"
}]
}]

and the class to which I am converting is

import {Type} from 'class-transformer';
/**

  • Model for dropdown name and corresponding array of values of ApplicationValue type.
  • @author [email protected] (Pankaj Khurana)
    */
    export class ApplicationType {
    id: number;
    name: string;
    @type(() => ApplicationValue)
    values: Array;
    }

/**

  • This signifies the value populated in the dropdown and its corresponding id.
  • As this class cannot stand alone, thereby making it a part of ApplicationType only.
  • @author [email protected] (Pankaj Khurana)
    */
    export class ApplicationValue {
    id: number;
    value: string;
    }

Please suggest if I am missing something.

truncate object .

hi, how can i truncate object that i get from the client.
suppose i have class:

class user{
id:string;
appId:string;
}

and i get userViewModel from client that contains appName;

what that i did, i set all property to null, and do:

obj = new type();
                _.each(_.keys(obj), key =>{
                    obj[key] = data[key];
                    if (obj[key] === null) obj[key] = undefined; 
                })

there is a better way to do it with your module?

tanks.

Date object is not serializing

I'm using Type decorator for Date. Even after it's not serializing and json has empty object instead.
Sample code:

class d {
id:number;
@type(() => Date)
da: Date;
}

let obj:d = new d();
obj.id = 1;
obj.da = new Date();

console.log(serialize(obj));

Output
{ id: 1, da: {} }

Is this an issue or am I missing something here?

Note: deserializing a string date to date object is working though.

Annotate Objects as Maps

How can I annotate a member field of a class to be converted to a Map<string, Dimension>?

@Type(() => Map<string, Dimension>) is not syntactically correct.

The data coming from my API are like that:

      "dimensions":{  
         "administrativeClassification":{  
            "key_attribute":"notation",
            "hierarchy":"administrativeClassification",
            "label":"Municipality Office",
            "ref":"administrativeClassification",
            "orig_dimension":"administrativeClassification",
            "attributes":{  
               "prefLabel":{  
                  "column":"skos:prefLabel",
                  "label":"preferred label",
                  "orig_attribute":"prefLabel",
                  "ref":"administrativeClassification.prefLabel",
                  "datatype":"string"
               },
               "inScheme":{  
                  "column":"skos:inScheme",
                  "label":"is in scheme",
                  "orig_attribute":"inScheme",
                  "ref":"administrativeClassification.inScheme",
                  "datatype":"string"
               },
               "topConceptOf":{  
                  "column":"skos:topConceptOf",
                  "label":"is top concept in scheme",
                  "orig_attribute":"topConceptOf",
                  "ref":"administrativeClassification.topConceptOf",
                  "datatype":"string"
               },
               "altLabel":{  
                  "column":"skos:altLabel",
                  "label":"alternative label",
                  "orig_attribute":"altLabel",
                  "ref":"administrativeClassification.altLabel",
                  "datatype":"string"
               },
               "notation":{  
                  "column":"skos:notation",
                  "label":"notation",
                  "orig_attribute":"notation",
                  "ref":"administrativeClassification.notation",
                  "datatype":"string"
               }
            },
            "cardinality_class":null,
            "key_ref":"administrativeClassification.notation",
            "label_attribute":"prefLabel",
            "label_ref":"administrativeClassification.prefLabel"
         },
         "economicClassification":{  
            "key_attribute":"notation",
            "hierarchy":"economicClassification",
            "label":"KA of Expenditure",
            "ref":"economicClassification",
            "orig_dimension":"economicClassification",
            "attributes":{  
               "prefLabel":{  
                  "column":"skos:prefLabel",
                  "label":"preferred label",
                  "orig_attribute":"prefLabel",
                  "ref":"economicClassification.prefLabel",
                  "datatype":"string"
               },
               "inScheme":{  
                  "column":"skos:inScheme",
                  "label":"is in scheme",
                  "orig_attribute":"inScheme",
                  "ref":"economicClassification.inScheme",
                  "datatype":"string"
               },
               "broader":{  
                  "column":"skos:broader",
                  "label":"has broader",
                  "orig_attribute":"broader",
                  "ref":"economicClassification.broader",
                  "datatype":"string"
               },
               "notation":{  
                  "column":"skos:notation",
                  "label":"notation",
                  "orig_attribute":"notation",
                  "ref":"economicClassification.notation",
                  "datatype":"string"
               }
            },
            "cardinality_class":null,
            "key_ref":"economicClassification.notation",
            "label_attribute":"prefLabel",
            "label_ref":"economicClassification.prefLabel"
         },
         "functionalClassification":{  
            "key_attribute":"notation",
            "hierarchy":"functionalClassification",
            "label":"Municipality Office - KAE Programme",
            "ref":"functionalClassification",
            "orig_dimension":"functionalClassification",
            "attributes":{  
               "prefLabel":{  
                  "column":"skos:prefLabel",
                  "label":"preferred label",
                  "orig_attribute":"prefLabel",
                  "ref":"functionalClassification.prefLabel",
                  "datatype":"string"
               },
               "inScheme":{  
                  "column":"skos:inScheme",
                  "label":"is in scheme",
                  "orig_attribute":"inScheme",
                  "ref":"functionalClassification.inScheme",
                  "datatype":"string"
               },
               "broader":{  
                  "column":"skos:broader",
                  "label":"has broader",
                  "orig_attribute":"broader",
                  "ref":"functionalClassification.broader",
                  "datatype":"string"
               },
               "notation":{  
                  "column":"skos:notation",
                  "label":"notation",
                  "orig_attribute":"notation",
                  "ref":"functionalClassification.notation",
                  "datatype":"string"
               }
            },
            "cardinality_class":null,
            "key_ref":"functionalClassification.notation",
            "label_attribute":"prefLabel",
            "label_ref":"functionalClassification.prefLabel"
         },
         "budgetPhase":{  
            "key_attribute":"budgetPhase",
            "hierarchy":"budgetPhase",
            "label":"Budget Phase",
            "ref":"budgetPhase",
            "orig_dimension":"budgetPhase",
            "attributes":{  
               "prefLabel":{  
                  "column":"skos:prefLabel",
                  "label":"preferred label",
                  "orig_attribute":"prefLabel",
                  "ref":"budgetPhase.prefLabel",
                  "datatype":"string"
               },
               "definition":{  
                  "column":"skos:definition",
                  "label":"definition",
                  "orig_attribute":"definition",
                  "ref":"budgetPhase.definition",
                  "datatype":"string"
               },
               "inScheme":{  
                  "column":"skos:inScheme",
                  "label":"is in scheme",
                  "orig_attribute":"inScheme",
                  "ref":"budgetPhase.inScheme",
                  "datatype":"string"
               },
               "topConceptOf":{  
                  "column":"skos:topConceptOf",
                  "label":"is top concept in scheme",
                  "orig_attribute":"topConceptOf",
                  "ref":"budgetPhase.topConceptOf",
                  "datatype":"string"
               },
               "budgetPhase":{  
                  "column":"http:\/\/data.openbudgets.eu\/ontology\/dsd\/greek-municipalities\/dimension\/budgetPhase",
                  "label":"Budget Phase",
                  "orig_attribute":"budgetPhase",
                  "ref":"budgetPhase.budgetPhase",
                  "datatype":"string"
               }
            },
            "cardinality_class":null,
            "key_ref":"budgetPhase.budgetPhase",
            "label_attribute":"prefLabel",
            "label_ref":"budgetPhase.prefLabel"
         }
      },

So I want the dimensions field to get a value which is a Map of Dimensions, with strings as keys.

Reverse 'Transform'?

Is there a way to Transform for both serialization and deserialization? I want to convert an object into it's name on classToPlain, and back into an object from a different source on plainToClass.

plainToInstance

I need to deserialize to an existing class instance.
For example in Aurelia I don't have control of the instantiation of the view-model objects and have to perform the deserialization from the constructor.
Also I expect to receive data updates for the objects and it would be much easier to just update the properties, rather than change the whole object.

nested array

Hello, i am very happy to use this library. I have a question, how would i use this if i have an array like this. Is this the correct way?

export class ManagerCollection extends Array<User> {}

    @ArrayType(() => ManagerCollection)
    public managers: {
        owners:User[],
        admins:User[],
    }

Different class by value

Hi,

I have a tree structure in json. Imagine a folder-file system, with various different file types. I want the files array to be different classes based on the extension of the entry.

I played around with the @Transform decorator but didn't have any success. Is this supported?

Thanks for your help.
Phillip

Date Nullable

Hello,
the plainToClass doesnt not seams to deals with nullable Date:

Example :

@Type(() => Date)
public Act_Date_Reunion_Exp: Date;

=> if jsonObject Act_Date_Reunion_Exp is null , set classObject to "1970-01-01 01:00:00.000" Date

Example 2 :

// no typing @Type(() => Date)
public Act_Date_Reunion_Exp: Date;

=> if jsonObject Act_Date_Reunion_Exp is null , set classObject to new Date() Date

Example 3

 @Transform(value =>moment(value), { toClassOnly: false })
 public Act_Date_Reunion_Exp: Moment;
=>throw error : target.prototype in findMetadatas() , target is null

Maybe i'm not doing this right
Any Ideas ?

Exclude nested propery object

hi,
I have the following structure:

@Exclude()
export class Menu{
    @Expose() _id:string;
    @Expose() name:string;
    @Expose() dishes:DishNenu[];
} 

export class MenuViewModel extends Menu{
    dishes:DishesNenuViewModel[] = [];
}

@Exclude()
export class DishesNenu{
    @Expose()  _id?:string;
     @Expose() price?:number;
}

@Exclude()
export class DishesNenuViewModel extends DishesNenu{
   name?:string;
   categoryName?:string;
}

plainToClass(Menu, menu) not exloded the DishesNenuViewModel properties...

Transforming Enum

Hi,

Is it possible to transform ENUM to String and String to ENUM?

thanks
Karthik

plainToClass : Type 'XX[]' is not assignable to type 'XX'

Using webpack and angular2 + Webstorm, I've got an error ...

These 2 methods have the same name but one is for array..

export declare function plainToClass2<T, V extends Array>(cls: ClassType, plain: V, options?: ClassTransformOptions): T[];
export declare function plainToClass<T, V>(cls: ClassType, plain: V, options?: ClassTransformOptions): T;

I have a class XX in TypeScript

private _myVar : XX;
....
this._myVar = plainToClass(XX, obj['xx'])

Webstorm shows it in red..... and webpack doesn't want to compile...

I have to rename this function so that it works (I don't use arrays).
export declare function plainToClass2<T, V extends Array>(cls: ClassType, plain: V, options?: ClassTransformOptions): T[];

thank you for your help

feat: transform class including dictionary type properties

Transforming Class which have a nested Class or Class[] type properties is working well.
Great Job!

But could I also transform Class with dictionary type properties?

import {Type, classToPlain} from "class-transformer";

export interface PhotoList {
    [id: string]: Photo
}

export class Album {
    id: number;
    name: string;
    @Type(() => Photo, {dictionaryType: true})  // telling it it's a dictionaryType like this...
    photos:PhotoList = {};
}

export class Photo {
    id: number;
    filename: string;
}

let plainAlbum = classToPlain(myAlbum);
let restoredAlbum = plainToClass(plainAlbum)

isCircular() cause performance issues

It seems that isCircular() is very expensive method in terms of CPU.
I tested plainToClass() with array of 10K objects (each item has date, string, and array of number fields).
isCircular() consumes 88% of the CPU time (5.8sec).
In addition, no need to check for circular references in case of deserializing (deserialize() or deserializeArray()), as circular reference can't happen after JSON.parse().
IMO, the solution for this is to expose a "skipCircularCheck" option in ClassTransformOptions, so the user can decide whether to include circular check or no. I tested such a solution and the result is extremely good.

plainToClass() of 10K objects With circular check:
capture

plainToClass() of 10K objects Without circular check:

capture2

Does not seem to work with generic object

I have a class with an array of generic objects. I tried specifying the @type decorator but it doesn't seem to be working. Am I doing something wrong or are generics not supported? Thank you.

class JsonObject {
@type(() => KeyValuePair<Date, number>)
public Series: KeyValuePair<Date, number>[] = [];
}

TypeError: Reflect.getMetadata is not a function

The readme says that reflect-metadata should be imported once - "and make sure to import it in a global place, like app.ts". Perhaps I'm missing something here, but if I import it in the root of my React app (I'm using babel to transpile), the transformer complains with the error above. It works only if I move the import 'reflect-metadata' to the actual class that is being serialized. Is that expected behavior?

Typescript error converting a single plain object to a Class

Hi,
I tried this library and played a little with your example. My configuration is the following Angular1 + typescript + webpack. I installed your library into my project with npm.

In your example, in users.json, you are returning an array of user objects. To my need, I returned only one user object. I then wrote a service like this one :

export class UserService {

  constructor(private $http: ng.IHttpService) {}

  getUser(): ng.IPromise<User> {
    return this.$http
      .get('assets/user.json')
      .then((response: any) => response.data)
      .then((response: any) => {
        let user = plainToClass(User, response);
        console.log('user', user);
        return user;
      });
  }
}

I have the following error in my console :

ERROR in ./src/app/services/user/user.service.ts
(9,12): error TS2322: Type 'IPromise<User[]>' is not assignable to type 'IPromise'.
Type 'User[]' is not assignable to type 'User'.
Property 'id' is missing in type 'User[]'.

The code is working because I can see the console.log and have the right values. But this error prevents me from building the code. The problem is that in the npm package, I have an index.d.ts and the plainToClass is pointing to the array version instead of the single object, i.e.

export declare function plainToClass<T, V extends Array<any>>(cls: ClassType<T>, plain: V, options?: ClassTransformOptions): T[];

instead of

export declare function plainToClass<T, V>(cls: ClassType<T>, plain: V, options?: ClassTransformOptions): T;

PS : I have the 0.1.0-beta2 version installed.

Typings

Hello, I see your package really useful for me, but I have troubles with typings. Could you please instruct me how to install typings for your package? Running "typings install" does not change anything.

Thanks, Matt

[Bug] Metadata colliding with Angular 2

When using this library with angular 2 and webpack the metadata get's messed up, for example we have 1 service which we use the @type decorator and it works before putting it, however the instant we add the decorator the app breaks in a weird way, the error yells for another unrelated component that just happens to use the service:

image

Here's the line in question, when we comment this the app works again:
image

It's breaking with the native Date class of Javascript.

Bar[] vs Array<Bar>

I encountered the following issue

newValue_1.push is not a function
   at http://localhost:3000/main.bundle.js:217:36
   at Array.forEach (native)
   at TransformOperationExecutor.transform (http://localhost:3000/main.bundle.js:209:19)
   at _loop_1 (http://localhost:3000/main.bundle.js:332:45)
   at TransformOperationExecutor.transform (http://localhost:3000/main.bundle.js:355:17)
   at ClassTransformer.plainToClass (http://localhost:3000/main.bundle.js:143:25)
   at Object.plainToClass (http://localhost:3000/main.bundle.js:624:29)

After some testing i found out that Bar[] works fine and Array<Bar> doesnt

Works

@Type(() => Bar)
Bars: Bar[] = new Bar[]();

Doesn't work

@Type(() => Bar)
Bars: Array<Bar> = new Array<Bar>();

Issue?
After some digging i found out that the reflected type was incorrect.

The reflectedType is reflectedType:Object()

TransformOperationExecutor.prototype.getReflectedType = function (target, propertyName) {
        if (!target)
            return undefined;
        var meta = storage_1.defaultMetadataStorage.findTypeMetadata(target, propertyName);
        return meta ? meta.reflectedType : undefined;
    };

Versions
"class-transformer": "0.1.6",
"reflect-metadata": "0.1.8"

Importing the correct Function

I'm getting the following error while trying to convert a Json to Plain Object

Type 'VdUser[]' is not assignable to type 'VdUser'.

This is the code line

let vduser:VdUser = plainToClass(VdUser, response.json());

vdUser is just a plain typescript class and I don't see any problem with the code, I think tsLint is taking the wrong function when validating the code.

is there a way I can specifically import the function ?

ArrayType bug?

hello,
i've started to get this error, i've upgraded to class-transformer

/project/node_modules/class-transformer/index"' has no exported member 'ArrayType'.

also, why do i get error on this code,

private user:User;
...
this.user = <User>plainToClass(User, data);

Error TS2352: Neither type 'User[]' nor type 'User' is assignable to the other.

DevTools failed to parse SourceMap

Since adding Class Transformer to my project, I'm getting the error:

DevTools failed to parse SourceMap: http://localhost:62691/scripts/TransformMetadata.js.map

Iโ€™m building my project Webpack and the TS-Loader module, if that's of any relevance. My tsconfig.json also has SourceMap set to false, so there shouldn't be any getting generated anyway!

Is this in issue with Class Transformer or with the Reflect Metadata package? Any help is greatly appreciated.

Thanks,

Dylan

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.