class-validators嵌套数组验证:多层错误提取通用方案问询
解决class-validator嵌套验证错误信息的通用提取问题
场景与问题
我需要验证通过Postman发送的对象数组请求体:
{ "pit_fee": [ { "range": [1,2], "fee":25 }, { "range": [3,4], "fee":30 } ] }
使用class-validator定义了如下验证Schema:
export class PitFeeObject { @IsNumber({}, { each: true }) range: number[]; @IsNumber() fee: number; } export class CreateConfigSchema { @IsArray() @ValidateNested({ each: true }) pit_fee: PitFeeObject[]; }
同时编写了验证中间件处理请求体验证:
const validationMiddleware = ( type: any, value: string | 'body' | 'query' | 'params' = 'body', skipMissingProperties = false, whitelist = true, forbidNonWhitelisted = true, ): RequestHandler => { return (req, res, next) => { validate(plainToInstance(type, req[value]), { skipMissingProperties, whitelist, forbidNonWhitelisted }).then((errors: ValidationError[]) => { if (errors.length > 0) { const message = errors.map((error: ValidationError) => Object.values(error.constraints)).join(', '); next(new HttpException(400, message)); } else { next(); } }); }; }; export default validationMiddleware;
当前遇到的问题是:@ValidateNested()生成的错误并非直接存放在error.constraints中,而是位于多层error.children嵌套结构里。如果通过固定层数的条件判断提取错误,无法适配更复杂的多层嵌套对象验证场景,需要一个通用的错误提取方法。
通用错误提取方案
通过递归遍历ValidationError结构,可以实现任意层级的错误信息收集,无需固定嵌套层数判断。
1. 编写递归错误提取辅助函数
import { ValidationError } from 'class-validator'; function extractValidationErrors(errors: ValidationError[]): string[] { const errorMessages: string[] = []; errors.forEach(error => { // 收集当前错误节点的约束提示 if (error.constraints) { errorMessages.push(...Object.values(error.constraints)); } // 递归处理子节点错误 if (error.children && error.children.length > 0) { errorMessages.push(...extractValidationErrors(error.children)); } }); return errorMessages; }
2. 修改验证中间件的错误处理逻辑
将原中间件中的错误信息拼接部分替换为上述辅助函数:
const validationMiddleware = ( type: any, value: string | 'body' | 'query' | 'params' = 'body', skipMissingProperties = false, whitelist = true, forbidNonWhitelisted = true, ): RequestHandler => { return (req, res, next) => { validate(plainToInstance(type, req[value]), { skipMissingProperties, whitelist, forbidNonWhitelisted }).then((errors: ValidationError[]) => { if (errors.length > 0) { // 使用递归函数提取所有层级的错误信息 const message = extractValidationErrors(errors).join(', '); next(new HttpException(400, message)); } else { next(); } }); }; }; export default validationMiddleware;
方案优势
- 自动适配任意层级的嵌套验证结构,无论是数组嵌套对象、对象嵌套对象数组还是更深层级的嵌套,都能正确提取所有错误信息
- 代码逻辑简洁可维护,无需根据不同的嵌套结构修改提取逻辑
内容的提问来源于stack exchange,提问作者Bigbool98
相关产品推荐
相关产品推荐

