Let's start with a simple, unambiguous example: say we have a User JSON object. This is the data I receive from fetch():
{
"user_name": "NSExceptional"
}
And I want to map it to a class that looks like this:
class User {
// I want to populate this from the user_name key
username: string;
}
My question is: with this library, how do I do that? At first glance of the README, I would try this:
class User {
@Expose({ name: 'user_name' })
username: string;
}
Is this correct?
Because upon further reading of your README example, I don't quite understand this part of the example:
@Expose({ name: 'fullName' })
getFullName() {
return this.firstName + ' ' + this.lastName;
}
What is @Expose({ name: 'fullName' }) doing here? It looks like it's enabling you to access getFullName() with user.fullName(). This makes me wonder about whether @Expose on properties also works "backwards" like this, which would be weird and wrong:
class User {
@Expose({ name: 'username' })
user_name: string;
}
Hello NSExceptional, as far as my knowledge goes, the @Expose decorator expose what your getters and methods return. It can also change the name of a property. In your case, the last example is the correct one where it takes the user_name property of your object and rename it into the username property of the class
I also find the work of the Expose decorator strange, or don't understand how it should work. I just follow the documentation examples and created the minimum required code
import "reflect-metadata";
import "es6-shim";
import { Expose, plainToClass } from "class-transformer";
const user = {
id: 1,
firstName: "Johny",
lastName: "Cage",
age: 27,
}
export class User {
id: number;
@Expose({
name: "name",
})
firstName: string;
lastName: string;
age: number;
}
console.log(plainToClass(User, user));
However, instead of the expected Name field that I added to Expose, I get undefined in firstname.
weslyg@pc:~/test-transform$ ts-node main.ts
User { id: 1, firstName: undefined, lastName: 'Cage', age: 27 }
I use ts-node and the following tsconfig to run this code
{
"compilerOptions": {
"module": "commonjs",
"declaration": true,
"removeComments": true,
"emitDecoratorMetadata": true,
"experimentalDecorators": true,
"allowSyntheticDefaultImports": true,
"target": "es2017",
"sourceMap": true,
"outDir": "./dist",
"baseUrl": "./",
"incremental": true,
"suppressImplicitAnyIndexErrors": true,
"resolveJsonModule": true,
"strict": false
}
}
Apparently I'm missing something, but I can't figure out what :(
I think I'm just fighting the wrong way )
classToPlain work for me.
import "reflect-metadata";
import "es6-shim";
import { classToPlain, Expose, plainToClass } from "class-transformer";
const user = {
id: 1,
firstName: "Johny",
lastName: "Cage",
age: 27,
};
export class User {
id: number;
@Expose({
name: "login",
})
firstName: string;
lastName: string;
age: number;
constructor(partial: Partial<User> = {}) {
Object.assign(this, partial);
}
}
console.log(classToPlain(new User(user)));
weslyg@pc:~/test-transform$ ts-node main.ts
{ id: 1, login: 'Johny', lastName: 'Cage', age: 27 }
@WeslyG unrelated but you can prefix a code block with the language you're about to use and it will syntax highlight it. For example,
````
// JSON code here
````
This works for json or js or ts etc
The @Expose decorator simply takes the value of property or result of the getter and expose it in the result instead of the original field when when calling classToPlain. This also works in the other direction when calling plainToClass the transformation will take the @Expose decorator into account and populate the correct property name.
If you want to make it work only in one direction you need to use the toPlainOnly or toClassOnly option.
import 'reflect-metadata';
import { plainToClass, classToPlain, Exclude, Expose } from './index';
export class TestWithoutExclude {
@Expose({ name: 'first_name'})
public firstName!: string;
}
@Exclude()
export class TestWithExclude {
@Expose({ name: 'first_name' })
public firstName!: string;
}
const withoutExcludeInstance = new TestWithoutExclude();
const withExcludeInstance = new TestWithExclude();
withoutExcludeInstance.firstName = 'John';
withExcludeInstance.firstName = 'John';
console.log(classToPlain(withoutExcludeInstance));
console.log(classToPlain(withExcludeInstance));
// { first_name: 'John' }
// { first_name: 'John' }
console.log(plainToClass(TestWithoutExclude, { first_name: 'John' }));
console.log(plainToClass(TestWithExclude, { first_name: 'John' }));
// TestWithoutExclude { firstName: 'John' }
// TestWithExclude { firstName: John }
console.log(plainToClass(TestWithoutExclude, { firstName: 'John' }));
// returns TestWithExclude { firstName: undefined }
This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Most helpful comment
@WeslyG unrelated but you can prefix a code block with the language you're about to use and it will syntax highlight it. For example,
````
````
This works for
jsonorjsortsetc