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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 20:25:33