如何在Nest.js应用中对REST API的动态属性名Tag对象做校验
Nest.js class-validator 动态Tag属性校验实现方案
核心实现思路是通过class-validator提供的自定义校验装饰器能力,覆盖动态属性的规则校验,具体操作步骤如下:
步骤1:实现自定义校验装饰器
新建自定义装饰器,封装Tag对象的所有校验规则,同时兼容普通对象和Map两种Tag定义形式:
import { registerDecorator, ValidationOptions, ValidationArguments } from 'class-validator'; export function IsValidTag(validationOptions?: ValidationOptions) { return function (target: Function) { registerDecorator({ name: 'isValidTag', target: target, options: validationOptions, validator: { validate(value: any, args: ValidationArguments) { // 适配普通对象类型的Tag if (typeof value === 'object' && value !== null && !Array.isArray(value)) { const keys = Object.keys(value); // 校验Tag仅含1个属性 if (keys.length !== 1) return false; const key = keys[0]; const val = value[key]; // 校验键规则:长度1-255,不含: if (typeof key !== 'string' || key.length < 1 || key.length > 255 || !/^[^:]+$/.test(key)) { return false; } // 校验值规则:字符串,长度1-255 if (typeof val !== 'string' || val.length < 1 || val.length > 255) { return false; } return true; } // 适配Map类型的Tag if (value instanceof Map) { if (value.size !== 1) return false; const [key, val] = value.entries().next().value; // 校验键规则 if (typeof key !== 'string' || key.length < 1 || key.length > 255 || !/^[^:]+$/.test(key)) { return false; } // 校验值规则 if (typeof val !== 'string' || val.length < 1 || val.length > 255) { return false; } return true; } return false; }, defaultMessage(args: ValidationArguments) { return 'Tag对象不符合规则:仅能包含1个键值对,键长度为1-255且不能包含":",值为长度1-255的字符串'; } } }); }; }
步骤2:修饰Tag类和Payload DTO
2.1 修饰Tag类
直接给你定义的Tag类加自定义装饰器即可:
// 普通动态对象形式 @IsValidTag() export class Tag { [key: string]: string; } // 或者Map继承形式 @IsValidTag() export class Tag extends Map<string, string> {}
2.2 调整Payload DTO
注意要引入class-transformer的@Type装饰器,确保嵌套对象能被正确转换触发校验:
import { Type } from 'class-transformer'; import { ArrayMaxSize, ArrayMinSize, IsArray, ValidateNested } from 'class-validator'; import { ApiProperty } from '@nestjs/swagger'; export class Payload { // ...其他属性 @IsArray() @ArrayMinSize(1) @ArrayMaxSize(11) @ValidateNested() @Type(() => Tag) // 替换你原来的@ValidateType,这是class-transformer的标准装饰器 @ApiProperty() tags: Tag[]; }
步骤3:开启全局校验管道转换
在项目入口main.ts中配置全局ValidationPipe,开启transform配置,确保请求普通对象能被转换为DTO类实例触发校验:
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, // 必须开启,否则嵌套校验不生效 // 其他可选配置,比如whitelist: true自动剔除未声明的属性 })); await app.listen(3000); } bootstrap();
可选优化
如果需要更精细化的错误提示,可以在校验逻辑中记录错误类型,在defaultMessage中返回对应提示即可。
内容的提问来源于stack exchange,提问作者Serhii
相关产品推荐
相关产品推荐

