You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修改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状态码和通用错误提示
  • 成功响应也做了优化,默认将返回数据放入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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 22:12:18