11

I am trying to serialize nested objects using a class transformer. I have two dtos like below. When I am trying to serialize using plainToClass the nested object gets removed from the output. only getting the parent object's data.

User dto:

export class UserDto extends AbstractDto {
    @Expose()
    email: string;

    @Expose()
    first_name: string;

    @Expose()
    last_name: string;

    @Expose()
    profile: ProfileDto

}

Profile dto:

export class ProfileDto extends AbstractDto {
    @Expose()
    date_of_birth: string;

    @Expose()
    address: string;

    @Expose()
    pincode: string;
}

Serializer:

const serialized = plainToClass(UserDto, user, {
    excludeExtraneousValues: true,
});

Expected Output:

{
    email:'[email protected]',
    first_name: 'test',
    last_name: 'test',
    profile: {
        date_of_birth: '',
        address: '',
        pincode: ''
    }
}

2 Answers 2

26

I have found the answer here Link. If I add enableImplicitConversion: true along with the @Type decorator then it is working as expected.

export class UserDto extends AbstractDto {
    @Expose()
    email: string;

    @Expose()
    first_name: string;

    @Expose()
    last_name: string;

    @Expose()
    @Type(() => ProfileDto)
    profile: ProfileDto

}

Serializer:

const serialized = plainToClass(UserDto, user, {
    excludeExtraneousValues: true,
    enableImplicitConversion: true
    
});
Sign up to request clarification or add additional context in comments.

2 Comments

If you're using class-transformer and class-validator together then you usually do not want to enable implicit conversion according to the docs github.com/typestack/class-transformer#implicit-type-conversion Issue is things like myField: string will pretty much always pass validation as almost everything can be converted to a string, including objects etc.
@TomManterfield I just ran into what you're referring to. Booleans will always be true even when set to strings. Do you have an alternative option for nested serialization?
2

This question is not related to NestJS, but purely to class-transformer. NestJS might happen to use the class-validator & class-transformer packages as part of its pipes feature, but in the context of this question NestJS doesn't even need to be considered.

Let's assume you have two classes, Cat and Owner. An owner can have a cat.

class Cat {
  @Expose()
  name: string;

  @Expose()
  age: number;

  favoriteFood: string;

  constructor(name: string, age: number, favoriteFood: string) {
    this.name = name;
    this.age = age;
    this.favoriteFood = favoriteFood;
  }
}

class Owner {
  @Expose()
  name: string;

  @Expose()
  cat: Cat;

  constructor(name: string, cat: Cat) {
    this.name = name;
    this.cat = cat;
  }
}

Let's instantiate an instance of each.

const cat = new Cat('Misty', 6, 'Dry cat food');
const owner = new Owner('Christophe', cat);

If you want to convert the owner instance back into a plain JavaScript object then use the instanceToPlain() function with the excludeAll strategy from class-transformer. The classToPlain() function is deprecated.

const serialized = instanceToPlain(owner, { strategy: 'excludeAll' });

That will only serialize the properties you decorated with the @Expose() decorator:

{ name: 'Christophe', cat: { name: 'Misty', age: 6 } }

The plainToClass() you used in your example is meant to convert a plain JavaScript back into an instance of the Owner class, or for "deserializing" rather.

For more information consult the class-transformer documentation.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.