diff --git a/packages/common/serializer/class-serializer.interceptor.ts b/packages/common/serializer/class-serializer.interceptor.ts index 7513447b054..8f1f4c0179e 100644 --- a/packages/common/serializer/class-serializer.interceptor.ts +++ b/packages/common/serializer/class-serializer.interceptor.ts @@ -1,8 +1,14 @@ +import { RETURN_TYPE_METADATA } from '../constants'; import { Observable } from 'rxjs'; import { map } from 'rxjs/operators'; import { Inject, Injectable, Optional } from '../decorators/core'; import { StreamableFile } from '../file-stream'; -import { CallHandler, ExecutionContext, NestInterceptor } from '../interfaces'; +import { + CallHandler, + ExecutionContext, + NestInterceptor, + Type, +} from '../interfaces'; import { ClassTransformOptions } from '../interfaces/external/class-transform-options.interface'; import { TransformerPackage } from '../interfaces/external/transformer-package.interface'; import { loadPackage } from '../utils/load-package.util'; @@ -23,6 +29,7 @@ const REFLECTOR = 'Reflector'; export interface ClassSerializerInterceptorOptions extends ClassTransformOptions { transformerPackage?: TransformerPackage; + returnType?: Type; } @Injectable() @@ -45,15 +52,16 @@ export class ClassSerializerInterceptor implements NestInterceptor { intercept(context: ExecutionContext, next: CallHandler): Observable { const contextOptions = this.getContextOptions(context); - const options = { + const options: ClassSerializerInterceptorOptions = { ...this.defaultOptions, ...contextOptions, }; + const returnType = this.getReturnType(context); return next .handle() .pipe( map((res: PlainLiteralObject | Array) => - this.serialize(res, options), + this.serialize(res, { returnType, ...options }), ), ); } @@ -63,7 +71,7 @@ export class ClassSerializerInterceptor implements NestInterceptor { */ serialize( response: PlainLiteralObject | Array, - options: ClassTransformOptions, + options: ClassSerializerInterceptorOptions, ): PlainLiteralObject | Array { if (!isObject(response) || response instanceof StreamableFile) { return response; @@ -76,11 +84,26 @@ export class ClassSerializerInterceptor implements NestInterceptor { transformToPlain( plainOrClass: any, - options: ClassTransformOptions, + options: ClassSerializerInterceptorOptions, ): PlainLiteralObject { - return plainOrClass - ? classTransformer.classToPlain(plainOrClass, options) - : plainOrClass; + if (!plainOrClass) { + return plainOrClass; + } + if (!options.returnType) { + return classTransformer.classToPlain(plainOrClass, options); + } + if (plainOrClass instanceof options.returnType) { + return classTransformer.classToPlain(plainOrClass, options); + } + const instance = classTransformer.plainToClass( + options.returnType, + plainOrClass, + ); + return classTransformer.classToPlain(instance, options); + } + + private getReturnType(context: ExecutionContext): Type { + return this.reflector.get(RETURN_TYPE_METADATA, context.getHandler()); } protected getContextOptions(