使用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; }
问题原因
- 控制器参数类型错误:
@Body('call_transfers')的类型应为MediaAlphaCallTransferItem[],ping_id应为string,time应为number,当前类型定义完全错误。 - 未开启字段过滤配置:Class-validator仅负责参数校验,本身不处理多余字段过滤,需要配合NestJS的
ValidationPipe配置或Class-transformer实现自动过滤。 - 未使用完整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
相关产品推荐
相关产品推荐

