NestJS中如何使用class-validator校验form-data中的数字数组
问题解决:form-data格式下数字数组校验失败处理方案
问题根本原因
form-data 属于纯文本传输格式,原生不支持数字、数组等复杂数据类型,所有非二进制参数默认都会被解析为字符串/字符串数组。你当前的校验规则存在逻辑冲突:@Type(() => Number) 会尝试将字段值转为数字类型,但 @IsNumberString 要求传入的值必须是字符串格式的数字,二者互斥会直接触发校验失败。
适配方案(分两种传参场景)
场景1:前端按数组格式传参(推荐)
前端传参时用重复key的格式传递数组,示例:
tags[]=1 tags[]=2 tags[]=3
后端默认会将该格式解析为字符串数组 ["1","2","3"],对应调整 Dto 如下:
首先确保你已经安装了 class-transformer 和 class-validator 依赖,然后修改字段校验规则:
import { Transform } from 'class-transformer'; import { IsArray, IsBoolean, IsBooleanString, IsNotEmpty, IsNumberString, IsOptional, IsString, MaxLength, MinLength } from 'class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class CreatePostDto { @IsNotEmpty() @IsString() @MinLength(3) title: string; @ApiProperty({ type: 'string', format: 'binary' }) thumbnail: any; @IsNotEmpty() @IsString() @MinLength(20) @MaxLength(300) description: string; @IsNotEmpty() @IsString() @MinLength(20) body: string; @IsOptional() @IsArray() @IsNumberString({}, { each: true }) // 最后把字符串数组转成数字数组,符合类型定义 @Transform(({ value }) => value.map(item => Number(item))) tags: number[]; @IsOptional() @IsArray() @IsNumberString({}, { each: true }) @Transform(({ value }) => value.map(item => Number(item))) categories: number[]; // 原规则用@IsBooleanString对应类型应为string,需要boolean类型可改为下方注释的规则 @IsBooleanString() published: string; // @Transform(({ value }) => value === 'true') // @IsBoolean() // published: boolean; }
同时要确保你在 NestJS 全局启用的 ValidationPipe 开启了 transform 配置,示例:
// main.ts 中配置 app.useGlobalPipes(new ValidationPipe({ transform: true, // 必须开启,否则class-transformer规则不生效 whitelist: true // 可选,自动过滤Dto未声明的字段 }));
场景2:前端传逗号拼接的字符串
如果前端只能传逗号拼接的字符串格式,比如 tags=1,2,3,调整字段规则如下即可:
@IsOptional() @IsString() // 先把字符串按逗号拆分,转成数组再校验每个元素 @Transform(({ value }) => value.split(',')) @IsNumberString({}, { each: true }) @Transform(({ value }) => value.map(item => Number(item))) tags: number[];
验证效果
配置完成后,前端按对应格式传参即可通过校验,最终拿到的 tags 和 categories 字段会是符合类型定义的数字数组。
内容的提问来源于stack exchange,提问作者ShaSha
相关产品推荐
相关产品推荐

