Как отформатировать ответ перед отправкой в ​​Nest. js? - PullRequest
0 голосов
/ 12 февраля 2020

Я следовал документации и смог добавить перехватчик для сопоставления ответов.

Я хочу согласованный вывод json формата для ответов.

Как этого добиться с помощью перехватчика или с чем-то еще лучше, чем этот подход.

{
  "statusCode": 201,
  "message": "Custom Dynamic Message"
  "data": {
     // properties
     meta: {}
  }
}

transform.interceptor.ts

import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export interface Response<T> {
  statusCode: number;
  data: T;
}

@Injectable()
export class TransformInterceptor<T>
  implements NestInterceptor<T, Response<T>> {
  intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Observable<Response<T>> {
    return next
      .handle()
      .pipe(
        map((data) => ({
          statusCode: context.switchToHttp().getResponse().statusCode,
          data,
        })),
      );
  }
}

app.controller.ts

export class AppController {
      @Post('login')
      @UseGuards(AuthGuard('local'))
      @ApiOperation({ summary: 'Login user' })
      @ApiBody({ type: LoginDto })
      @ApiOkResponse({ content: { 'application/json': {} } })
      @UseInterceptors(TransformInterceptor)
      async login(@Request() req) {
        const result = await this.authService.login(req.user);
        return { message: 'Thank you!', result };
      }
}

1 Ответ

2 голосов
/ 12 февраля 2020

Если я понимаю, что вы делаете с вашим ответом контроллера и вашим общим ответом перехватчика, то вы можете сделать что-то похожее:

import {
  Injectable,
  NestInterceptor,
  ExecutionContext,
  CallHandler,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';

export interface Response<T> {
  statusCode: number;
  message: string;
  data: T;
}

@Injectable()
export class TransformInterceptor<T>
  implements NestInterceptor<T, Response<T>> {
  intercept(
    context: ExecutionContext,
    next: CallHandler,
  ): Observable<Response<T>> {
    return next
      .handle()
      .pipe(
        map((data) => ({
          statusCode: context.switchToHttp().getResponse().statusCode,
          message: data.message
          data: {
            result: data.result,
            meta: {} // if this is supposed to be the actual return then replace {} with data.result
          }
        })),
      );
  }
}

И сохранить ваш контроллер в виде {message: 'Custom message', result}.

Другим вариантом, который потребовал бы больше первоначального, но возможно более чистого кода, было бы создание собственного декоратора, который отражал бы значение (сообщение) из класса и метода, а затем извлекал это значение в перехватчике после введения отражателя, но опять же, это потребовало бы больше предварительных усилий для настройки.

...