Search code examples
mappingentitynestjsinterceptordto

Nestjs: Cast complex Entity to Dto


I'm trying to cast a complex Entity to a Dto. I would like to remove some values which are in the entity from the DTO.

My entity looks like this (For simplicity a large part of the entity is omitted):

export class ResultEntity {
    constructor(
        public id: string,
        public userId: string,
        public results: CalculationOutputEntity[] = [],
        public item: Item = new Item(),
    ) { }
}

export class Item {
    constructor(
        public privat: Private = new Private(),
        public state: State = new State(),
        public combined: number = 0,
    ) { }
}

export class State {
    constructor(
        public numberA: number = 0,
        public numberB: number = 0,
        public numberC: number = 0,
        public numberD: number = 0,
    ) { }
}

I have found a solution which works very well for simple entities: Cast entity to dto If I adopt this suggestion of the custom interceptor, removing the id or the whole item property works.

I have tried two possibilities tot define my DTOs:

  1. It returns only the id and the item as a whole.
@Exclude()
export class AdvisoryResultDto {
    @Expose()
    public id: string;
    public userId: string;
    public results: CalculationOutputDto[];
    @Expose()
    public item: Item;
}
  1. This solution returns everything except the item property.
export class AdvisoryResultDto {
    public id: string;
    public userId: string;
    public results: CalculationOutputDto[];
    @Exclude()
    public item: Item;
}

The problem now is that I want to remove only certain values within the item property. So for example the private field and within the state-property numberB.

I would like to have the possibility within the nested classes to remove single values also with Exclude().

So for example:

export class AdvisoryResultDto {
    public id: string;
    public userId: string;
    public results: CalculationOutputDto[];
    public item: Item;
}

export class Item {
    @Exclude()
    public privat: PrivateDto;
    public state: StateDto;
    public combined: number;
}

export class StateDto {
    public numberA: number;
    @Exclude()
    public numberB: number;
    public numberC: number;
    public numberD: number;
}

Unfortunately I can't find anything about this exact problem. To take over the mapping manually would also not be a solution, since the CalculationOutput is by far more complex and is nested with many classes and properties.

Am I just missing a small step or is it not possible with Expose and Exclude from the class-transformer? If not I would appreciate another solution.


Solution

  • So i found the soulution in the documentation of the class-transformer package: https://github.com/typestack/class-transformer#working-with-nested-objects

    I need to add the @Type-Decorator to nested classes

    The solution:

    @Expose()
    export class AdvisoryResultDto {
        public id: string;
        public userId: string;
        public results: CalculationOutputDto[];
        @Type(() => Item)
        public item: Item;
    }
    
    export class Item {
        @Exclude()
        @Type(() => PrivateDto)
        public privat: PrivateDto;
        @Expose()
        @Type(() => StateDto)
        public state: StateDto;
        public combined: number;
    }
    
    export class StateDto {
        public numberA: number;
        @Exclude()
        public numberB: number;
        public numberC: number;
        public numberD: number;
    }