NestJS中IsString校验报错:合法枚举值触发字符串校验失败
NestJS Class Validator处理逗号分隔枚举参数时触发IsString校验失败
问题描述
我在NestJS项目中创建了接收查询参数过滤数据的API,其中interior参数通过逗号分隔枚举值传递(例如api/endpoint?interior=FURNISHED,UNFURNISHED)。
使用Class Validator时,我通过@Transform将参数拆分为字符串数组,再匹配Prisma Client中的Interior枚举,但出现了“Interior must be a valid string”错误。
Interior枚举定义:
export const Interior: { FURNISHED: 'FURNISHED', SEMI_FURNISHED: 'SEMI_FURNISHED', UNFURNISHED: 'UNFURNISHED' };
查询参数DTO代码:
export class GetPropertiesQueryDto { @IsString({ message: 'Interior must be a valid string' }) @IsOptional() @Transform(({ value }) => value.split(',')) @IsEnum(Interior, { each: true, }) interior?: Interior[]; // 其他字段... }
传入非法枚举值时,会正确返回枚举值错误提示;但传入合法枚举值时,却触发IsString校验失败。请问问题出在哪里?是否属性类型必须与IsString校验匹配?
问题原因
- 装饰器执行顺序导致校验对象错误:class-transformer的
@Transform会在class-validator的校验装饰器之前执行,把原始的逗号分隔字符串转换为数组。而你放在最上方的@IsString校验的是转换后的数组值,数组不是字符串,因此触发校验错误。 - 属性类型与校验规则冲突:
interior属性的类型是Interior[](数组),但@IsString要求属性值必须是字符串类型,两者逻辑矛盾,必然导致校验失败。
解决办法
直接移除@IsString装饰器,并可在@Transform中添加原始值类型校验确保输入合法性,修改后的DTO代码如下:
export class GetPropertiesQueryDto { @IsOptional() @Transform(({ value }) => { // 确保原始参数是字符串,避免非字符串输入导致split报错 if (typeof value !== 'string') { return []; // 若需严格校验,可抛出错误: // throw new Error('Interior must be a comma-separated string'); } return value.split(','); }) @IsEnum(Interior, { each: true, message: 'Interior must be one of: FURNISHED, SEMI_FURNISHED, UNFURNISHED' }) interior?: Interior[]; // 其他字段... }
补充说明
- 如果需要支持查询参数的数组形式(例如
?interior=FURNISHED&interior=UNFURNISHED),NestJS的ValidationPipe默认会将这类参数解析为数组,此时可以去掉@Transform中的split逻辑,直接用@IsEnum({each: true})校验数组元素即可。 @IsEnum的each: true配置会自动遍历数组,校验每个元素是否属于枚举值,完全满足你的需求。
内容的提问来源于stack exchange,提问作者Rafat Rashid Rahi
相关产品推荐
相关产品推荐

