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

使用Class-validator验证请求参数(含对象数组)时过滤失败的问题

Class-validator 无法过滤多余参数问题解决

需求场景

需要实现一个包含对象数组、字符串和数字的Class-validator验证器,用于提取请求体中的指定参数,期望的参数结构如下:

{
  "call_transfers": [
    {"bid":33,"bid_id":"1239dasdj8","carrier":"Jimmies pizza", "qualification_duration":222},
    {"bid":28,"bid_id":"3234sdfJIA","carrier":"Krusty crabs", "qualification_duration":22},
    {"bid":19,"bid_id":"9anHXawefa","carrier":"Bikiny bottom", "qualification_duration":33}
  ],
  "ping_id": "adi2837dasdjc8",
  "time" : 0.123      
}

测试时使用了包含多余参数的请求体:

{
  "name" : "Juan",
  "email": "jcasdasda@gmail.com",
  "token" : "1oap8X8ase@#*&",
  "call_transfers": [
    {"bid":33,"bid_id":"1239dasdj8","carrier":"Jimmies pizza", "qualification_duration":222, "fakeParam":123},
    {"bid":28,"bid_id":"3234sdfJIA","carrier":"Krusty crabs", "qualification_duration":22, "fakeParam":123 },
    {"bid":19,"bid_id":"9anHXawefa","carrier":"Bikiny bottom", "qualification_duration":33,"fakeParam":123}
  ],
  "ping_id": "adi2837dasdjc8",
  "time" : 0.123,
  "authParameters": [{"id":123,"type":"user","value":"chocolates"}]
}

但目前无法正确过滤掉多余参数,当前使用的控制器和验证类代码如下:

当前控制器代码

setFlagsOnBid(
  @Body('call_transfers') call_transfers: MediaAlphaResponseItem,
  @Body('ping_id') ping_id: MediaAlphaResponseItem,
  @Body('time') time: MediaAlphaResponseItem,
){
  const filteredData = { call_transfers , ping_id , time };
  return filteredData;
}

当前验证类代码

export class MediaAlphaResponseItem {
    @ValidateNested({ each: true })
    @Type(() => MediaAlphaCallTransferItem)
    call_transfers: MediaAlphaCallTransferItem[];

    @IsString()
    ping_id:string;

    @IsNumber()
    time:number;
}

class MediaAlphaCallTransferItem {
    @IsNumber()
    bid:number;

    @IsString()
    bid_id:string;

    @IsString()
    carrier:string;

    @IsNumber()
    qualification_duration:number;
}

问题原因

  1. 控制器参数类型错误:@Body('call_transfers')的类型应为MediaAlphaCallTransferItem[],ping_id应为string,time应为number,当前类型定义完全错误。
  2. 未开启字段过滤配置:Class-validator仅负责参数校验,本身不处理多余字段过滤,需要配合NestJS的ValidationPipe配置或Class-transformer实现自动过滤。
  3. 未使用完整DTO接收请求体:单独提取请求体字段的方式无法利用类转换工具的自动过滤能力。

解决步骤

1. 配置全局ValidationPipe

在main.ts中开启参数转换和白名单过滤:

import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(
    new ValidationPipe({
      transform: true, // 自动将请求体转换为DTO类实例
      whitelist: true, // 自动过滤DTO中未定义的字段
      forbidNonWhitelisted: false, // 可选:设为true会对多余字段抛出错误,按需选择
    }),
  );
  await app.listen(3000);
}
bootstrap();

2. 修正验证类(可选,配合细粒度控制)

如果需要更精准的字段控制,可以结合Class-transformer的装饰器(需先安装:npm install class-transformer):

import { IsNumber, IsString, ValidateNested } from 'class-validator';
import { Type, Exclude, Expose } from 'class-transformer';

@Exclude() // 默认排除所有未标记@Expose的字段
export class MediaAlphaResponseItem {
  @Expose()
  @ValidateNested({ each: true })
  @Type(() => MediaAlphaCallTransferItem)
  call_transfers: MediaAlphaCallTransferItem[];

  @Expose()
  @IsString()
  ping_id: string;

  @Expose()
  @IsNumber()
  time: number;
}

@Exclude()
export class MediaAlphaCallTransferItem {
  @Expose()
  @IsNumber()
  bid: number;

  @Expose()
  @IsString()
  bid_id: string;

  @Expose()
  @IsString()
  carrier: string;

  @Expose()
  @IsNumber()
  qualification_duration: number;
}

3. 修正控制器代码

使用完整DTO接收整个请求体:

import { Body, Controller, Post } from '@nestjs/common';
import { MediaAlphaResponseItem } from './dto/media-alpha-response.dto';

@Controller('your-path')
export class YourController {
  @Post('set-flags-on-bid')
  setFlagsOnBid(@Body() filteredData: MediaAlphaResponseItem) {
    return filteredData;
  }
}

效果验证

修改完成后,用带多余参数的请求体测试,返回结果会自动过滤掉所有未在DTO中定义的字段(如name、fakeParam等),仅保留期望的参数结构。

内容的提问来源于stack exchange,提问作者user17281101

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 22:35:09