typestack / class-transformer Goto Github PK
View Code? Open in Web Editor NEWDecorator-based transformation, serialization, and deserialization between objects and classes.
License: MIT License
Decorator-based transformation, serialization, and deserialization between objects and classes.
License: MIT License
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.
Hi,
Is it possible to use the @type decorator to transform a date string into a moment object when calling plainToClass ?
Described in title - there probably should be ways to:
@Type(()=>String, { default: "" })
@Type(()=>String, { nullable: true })
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"
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:
Here's the line in question, when we comment this the app works again:
It's breaking with the native Date
class of Javascript.
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
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:
class-transformer
Notes:
ts-node/register
in my mocha
tests in package BI'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 ?
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
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';
/**
/**
Please suggest if I am missing something.
Hi,
Is it possible to transform ENUM to String and String to ENUM?
thanks
Karthik
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.
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.
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>[] = [];
}
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 ;-)
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 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
.
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.
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.
@Expose({ name: "something" })
This does not work. The property still has the same name and it's value is now undefined.
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...
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"
}
}]
}
I would expect a property which is undefined in the Class to not appear at all in the Plain object representation.
Or at least to have a flag to control this.
Is there any workaround?
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.
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[],
}
Is there a way to pass arguments to the class constructor on classToPlain or
plainToClass`?
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.
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
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.
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?
There is a mistake in documentation (I guess):
@Expose("uid")
id: number;
But Expose has only one argument - ExposeOptions
In such a case should be
@Expose({name: "uid"})
id: number;
I found that it seems that it cannot be detected, did I do something wrong?:
@Type(() => Album)
albums : {
[key : string]: Album
};
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.
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)
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?
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;
}
Hi, does the library support polymorphism? If so, are there any examples I can look into?
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
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;
}
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
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.
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!
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
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.
Need to create an example of usage with angular 2 in plunker. Pretty easy task, would be nice if someone pick this up.
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.
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?
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 ?
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:
plainToClass() of 10K objects Without circular check:
Just confirming if array to es6 Set works as you have specified in https://github.com/pleerock/class-transformer/blob/master/test/functional/es6-data-types.spec.ts
In my angular project, I get this error "ERROR TypeError: newValue_1.push is not a function
". es6 Map works fine.
To Reproduce:
Any new angular project created with @angular/cli and class-transformer will reproduce this.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.