在NestJS中使用class-validator自定义结构化验证错误响应
实现自定义参数校验错误响应格式
在NestJS中,要将class-validator返回的字符串数组错误信息转为包含字段名的对象数组,需要通过自定义异常过滤器重写默认的错误处理逻辑,具体步骤如下:
1. 创建自定义异常过滤器
新建过滤器文件(如src/common/filters/validation-exception.filter.ts),捕获BadRequestException并处理校验错误:
import { ExceptionFilter, Catch, ArgumentsHost, BadRequestException } from '@nestjs/common'; import { Response } from 'express'; import { ValidationError } from 'class-validator'; @Catch(BadRequestException) export class ValidationExceptionFilter implements ExceptionFilter { catch(exception: BadRequestException, host: ArgumentsHost) { const ctx = host.switchToHttp(); const response = ctx.getResponse<Response>(); const exceptionResponse = exception.getResponse() as { message: ValidationError[] | string[] }; // 转换校验错误为目标格式 const formattedErrors = Array.isArray(exceptionResponse.message) ? exceptionResponse.message.flatMap((error) => { if (typeof error === 'string') { return [{ field: 'unknown', error }]; } // 遍历字段的所有校验错误 return Object.values(error.constraints).map((msg) => ({ field: error.property, error: msg, })); }) : [{ field: 'unknown', error: exceptionResponse.message }]; response.status(exception.getStatus()).json({ message: formattedErrors, // 若需保留statusCode、error字段可取消注释 // statusCode: exception.getStatus(), // error: exception.name, }); } }
2. 注册全局过滤器
在main.ts中注册过滤器,让全局校验错误统一使用该处理逻辑:
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { ValidationExceptionFilter } from './common/filters/validation-exception.filter'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalFilters(new ValidationExceptionFilter()); await app.listen(3000); } bootstrap();
关键说明
- 过滤器自动捕获
ValidationPipe抛出的BadRequestException,从异常响应中提取原始ValidationError数组 - 通过
ValidationError的property(字段名)和constraints(错误信息),将每个校验错误转换为{ field: string, error: string }格式的对象 - 若只需在特定控制器/方法生效,可在对应位置使用
@UseFilters(ValidationExceptionFilter)装饰器替代全局注册
配置完成后,校验错误响应会符合预期格式:
{ "message": [ { "field": "title", "error": "Title is too long. Maximal length is 50 characters, but actual is testtesttesttesttesttesttesttesttesttesttesttesttesttesttest" }, { "field": "title", "error": "Title is too short. Minimal length is 10 characters, but actual is abc" } ] }
内容的提问来源于stack exchange,提问作者Shivansh Kumar
相关产品推荐
相关产品推荐

