如何修改NestJS中DTO校验失败的错误响应格式?
解决NestJS统一错误响应格式问题
你的现有拦截器只处理了成功响应的格式转换,没有捕获并处理异常流,所以DTO校验失败这类异常不会被格式化。需要修改拦截器,添加异常捕获逻辑,将所有错误统一转换为目标格式:
修改后的拦截器代码
import { Injectable, NestInterceptor, ExecutionContext, CallHandler, HttpException, ValidationException, } from '@nestjs/common'; import { Observable, throwError } from 'rxjs'; import { catchError, map } from 'rxjs/operators'; export interface StandardResponse<T> { statusCode: number; message: string; errors: T; data: []; } @Injectable() export class StandardResponseInterceptor<T> implements NestInterceptor<T, StandardResponse<T>> { intercept(context: ExecutionContext, next: CallHandler): Observable<StandardResponse<T>> { return next.handle().pipe( // 处理成功响应 map((responseData) => ({ statusCode: context.switchToHttp().getResponse().statusCode, message: '请求成功', errors: [], data: responseData || [], })), // 处理异常响应 catchError((error) => { let statusCode: number; let message: string; let errors: any[] = []; // 处理DTO校验错误(ValidationException) if (error instanceof ValidationException) { statusCode = error.getStatus(); message = '请求参数校验失败'; errors = error.getResponse().message as string[]; } // 处理其他HTTP异常 else if (error instanceof HttpException) { statusCode = error.getStatus(); message = error.message; const errorResponse = error.getResponse(); errors = typeof errorResponse === 'object' && (errorResponse as any).message ? [ (errorResponse as any).message ] : [ errorResponse ]; } // 处理未知异常 else { statusCode = 500; message = '服务器内部错误'; errors = [ error.message || '未知错误' ]; } // 返回标准化错误格式 return throwError(() => ({ statusCode, message, errors, data: [], })); }), ); } }
关键修改说明
- 添加
catchError操作符捕获所有异常流,包括DTO校验抛出的ValidationException - 针对不同异常类型做差异化处理:
- ValidationException:提取校验错误列表到
errors字段,统一设置提示消息为"请求参数校验失败" - HttpException:提取异常状态码和消息,兼容Nest自带的各种HTTP异常格式
- 未知异常:统一返回500状态码和通用错误提示
- ValidationException:提取校验错误列表到
- 成功响应也做了优化,默认将返回数据放入
data字段,errors设为空数组
生效方式
将该拦截器注册为全局拦截器,确保所有接口都生效:
// 在main.ts中 import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { StandardResponseInterceptor } from './interceptors/standard-response.interceptor'; async function bootstrap() { const app = await NestFactory.create(AppModule); // 注册全局拦截器 app.useGlobalInterceptors(new StandardResponseInterceptor()); await app.listen(3000); } bootstrap();
或者在模块中注册(局部生效):
// 在对应模块中 import { Module } from '@nestjs/common'; import { APP_INTERCEPTOR } from '@nestjs/core'; import { StandardResponseInterceptor } from './interceptors/standard-response.interceptor'; @Module({ providers: [ { provide: APP_INTERCEPTOR, useClass: StandardResponseInterceptor, }, ], }) export class AppModule {}
修改后,DTO校验失败的响应会变成:
{ "statusCode": 400, "message": "请求参数校验失败", "errors": [ "status must be one of the following values: Pending" ], "data": [] }
内容的提问来源于stack exchange,提问作者code_optimizer
相关产品推荐
相关产品推荐

