Search code examples
javascriptjsonnestjsinterceptortypescript-decorator

@UseInterceptors ignores @Expose and not working properly


I have created a custom Decorator and SerializeInterceptor class:

interface ClassConstructor {
    new (...args: any[]): {}
}

export function Serialize(dto: ClassConstructor) {
    return UseInterceptors(new SerializeInterceptor(dto));
}

export class SerializeInterceptor implements NestInterceptor {

    constructor(private dto: any) {}

    intercept(context: ExecutionContext, handler: CallHandler): Observable<any> {
        return handler.handle().pipe(
            map((data: any) => {
                return instanceToPlain(data);
            })
        );
    }
}

I use it in the controller such as this:

@Serialize(ReviewDto)

This is the returned JSON:

{
    "userComment": {
        "lastModified": {
            "seconds": "1660068559",
            "nanos": 957000000
        },
        "text": "\tGreat",
        "starRating": 5,
    },
    "developerComment": {
        "lastModified": {
            "seconds": "",
            "nanos": 0
        },
        "text": ""
    },
    "_id": {},
    "reviewId": "d8171d40-c930-44b6-ade4-bb8391e56cb5",
    "authorName": "Luis Garcia",
    "__v": 0
}

My problem is that inside the ReviewDto file I have set @Expose() decorator to both developerComment and authorName and it does not work. Also, why is it adding _id and __V to the JSON?


Solution

  • So the problem was that I didn't set the DTO class to the Interceptor, this is how I fixed it:

    export class SerializeInterceptor implements NestInterceptor {
    
        constructor(private dto: any) {}
    
        intercept(context: ExecutionContext, handler: CallHandler): Observable<any> {
            return handler.handle().pipe(
                map((data: any) => {
                    return plainToInstance(this.dto, data, {
                        excludeExtraneousValues: true
                    });
                })
            );
        }
    }
    

    And this is how to use it (inside the Controller):

    @Serialize(<DTO CLASS>)