如何在NestJS中为class-validator的@IsEnum设置自定义错误消息
NestJS class-validator枚举数组校验:精准提示非法值
问题说明
使用NestJS配合class-validator做枚举数组校验时,通过@IsEnum(EnumName, { each: true })装饰器校验,当输入包含非法值(比如枚举允许A/B/C,输入A,B1,C),默认错误提示仅显示each value in tag must be a valid enum value,无法明确指出具体哪个值不合法。需要返回包含非法值的精准提示,比如值B1不合法。
当前校验代码:
@IsEnum(EnumName, { each: true }) enumValues: EnumName[] = [];
默认错误响应:
response: { statusCode: 400, message: [ 'each value in tag must be a valid enum value' ], error: 'Bad Request' }, status: 400
解决方案
方法一:自定义错误消息(最简单实现)
class-validator的@IsEnum支持通过动态消息模板获取非法值,直接修改装饰器配置即可:
@IsEnum(EnumName, { each: true, message: (args) => `${args.value} 不是合法的枚举值,允许值为:${Object.values(EnumName).join(', ')}` }) enumValues: EnumName[] = [];
当输入A,B1,C时,错误消息会变为B1 不是合法的枚举值,允许值为:A,B,C,直接定位非法值。
方法二:自定义验证器(适配复杂场景)
如果需要批量校验并返回所有非法值,可自定义验证器实现:
- 创建验证器类
import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from 'class-validator'; import { EnumName } from './your-enum-file-path'; @ValidatorConstraint({ name: 'validEnumArray', async: false }) export class ValidEnumArrayValidator implements ValidatorConstraintInterface { validate(values: any[], args: ValidationArguments) { const validOptions = Object.values(EnumName); // 收集所有非法值并暂存到请求对象中 (args.object as any).invalidValues = values.filter(val => !validOptions.includes(val)); return (args.object as any).invalidValues.length === 0; } defaultMessage(args: ValidationArguments) { const invalidVals = (args.object as any).invalidValues; return `非法枚举值:${invalidVals.join(', ')},允许值为:${Object.values(EnumName).join(', ')}`; } }
- 在DTO中使用自定义验证器
import { Validate } from 'class-validator'; import { ValidEnumArrayValidator } from './your-validator-file-path'; @Validate(ValidEnumArrayValidator) enumValues: EnumName[] = [];
这种方式会一次性返回所有非法值,适合多错误场景的批量提示。
方法三:全局异常过滤器统一格式化响应
如果需要统一项目中所有验证错误的响应格式,可创建全局异常过滤器:
import { ExceptionFilter, Catch, ArgumentsHost } from '@nestjs/common'; import { ValidationException } from 'class-validator'; import { Response } from 'express'; @Catch(ValidationException) export class ValidationErrorFilter implements ExceptionFilter { catch(exception: ValidationException, host: ArgumentsHost) { const ctx = host.switchToHttp(); const res = ctx.getResponse<Response>(); const status = 400; // 格式化错误消息,这里适配方法一的自定义消息格式,若用默认消息可自行解析补充 const formattedMessages = exception.getResponse()['message'].map((msg: string) => msg); res.status(status).json({ statusCode: status, message: formattedMessages, error: 'Bad Request' }); } }
在main.ts中注册全局过滤器:
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { ValidationErrorFilter } from './validation-error.filter'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalFilters(new ValidationErrorFilter()); await app.listen(3000); } bootstrap();
内容的提问来源于stack exchange,提问作者user10874312
相关产品推荐
相关产品推荐

