NestJS中如何为@IsNotIn校验器抛出元数据信息
问题描述
我有如下NestJS DTO:
import { IsEmail, IsNotEmpty, IsNotIn } from 'class-validator'; import { AppService } from './app.service'; const restrictedNames = ['Name Inc', 'Acme Inc']; class DTO { @IsNotEmpty() name: string; @IsEmail() email: string; @IsNotEmpty() @IsNotIn(restrictedNames) orgName: string; }
我配置了全局ValidationPipe并自定义异常过滤器,返回包含校验失败详情的错误信息:
app.useGlobalPipes( new ValidationPipe({ exceptionFactory: (validationErrors: ValidationError[] = []) => { console.log(validationErrors); return new BadRequestException({ statusCode: HttpStatus.BAD_REQUEST, message: validationErrors.reduce((acc, error) => { acc[error.property] = Object.keys(error.constraints).map( (failed) => ({ failedValidation: failed, message: error.constraints[failed], }), ); return acc; }, {}), error: 'validation', }); }, }),
当前校验失败时返回的错误示例:
{"statusCode":400,"message":{"email":[{"failedValidation":"isEmail","message":"email must be an email"}],"orgName":[{"failedValidation":"isNotIn","message":"orgName should not be one of the following values: Name Inc, Acme Inc"}]},"error":"validation"}
但我希望@IsNotIn校验失败时,能把禁用的关键词以单独字段返回,期望返回格式如下:
{"statusCode":400,"message":{"email":[{"failedValidation":"isEmail","message":"email must be an email"}],"orgName":[{"failedValidation":"isNotIn","message":"orgName should not be one of the following values: Name Inc, Acme Inc", "data":{"reservedKeywords":["Name Inc","Acme Inc"]}}]},"error":"validation"}
现有异常过滤器无法获取装饰器元数据中的约束值,请问如何修改异常过滤器实现这个需求?
解决方案
要实现这个需求,你需要开启class-validator的上下文参数传递,然后针对isNotIn校验器提取约束值:
修改后的异常过滤器代码如下:
import { ValidationError } from 'class-validator'; import { BadRequestException, HttpStatus, ValidationPipe } from '@nestjs/common'; app.useGlobalPipes( new ValidationPipe({ exceptionFactory: (validationErrors: ValidationError[] = []) => { return new BadRequestException({ statusCode: HttpStatus.BAD_REQUEST, message: validationErrors.reduce((acc, error) => { acc[error.property] = Object.keys(error.constraints).map((failed) => { const errorDetail = { failedValidation: failed, message: error.constraints[failed], }; // 针对isNotIn校验器提取禁用关键词列表 if (failed === 'isNotIn') { const reservedKeywords = error.context?.constraints[0]; if (reservedKeywords) { errorDetail['data'] = { reservedKeywords }; } } return errorDetail; }); return acc; }, {}), error: 'validation', }); }, // 开启context选项,才能获取校验器的参数元数据 validationError: { target: false, // 可选:关闭返回目标类信息 value: false, // 可选:关闭返回字段值 context: true, // 关键配置:开启后可拿到校验器传入的参数 }, }), );
核心说明
- 开启
context配置:必须在validationError中设置context: true,class-validator才会把@IsNotIn传入的restrictedNames等参数存入ValidationError的context属性中。 - 针对性处理校验器:遍历约束失败项时,判断当前失败类型为
isNotIn,就从error.context.constraints[0]中取出禁用关键词列表,添加到data.reservedKeywords字段。 - 兼容性保障:该修改仅对
isNotIn校验器生效,不会影响其他校验器的错误返回格式。
内容的提问来源于stack exchange,提问作者Vishal Tyagi
相关产品推荐
相关产品推荐

