Skip to content

结构化验证 DTO

DTO 种类

  1. 响应 DTO:不仅用于请求校验,也可规范接口返回的数据格式(如隐藏敏感字段);
  2. 查询参数 DTO:配合 @Query() 校验 URL 查询参数(如分页参数 page/size);
  3. 嵌套 DTO:复杂数据结构可通过嵌套类实现多层校验。

class-validator 验证器

shell
# 引入
import { IsString, IsInt, IsEmail, IsNotEmpty, Min, Max, IsOptional } from 'class-validator';

# 常见验证装饰器
@IsString() - 必须是字符串
@IsInt() - 必须是整数
@IsNumber() - 必须是数字
@IsBoolean() - 必须是布尔值
@IsDate() - 必须是日期
@IsEmail() - 必须是有效的电子邮件地址
@IsNotEmpty() - 不能为空
@IsOptional() - 可选字段

# 数值验证
@Min(number) - 最小值
@Max(number) - 最大值
@IsPositive() - 必须是正数
@IsNegative() - 必须是负数

# 字符串验证
@Length(min, max) - 字符串长度范围
@Contains(seed) - 必须包含指定字符串
@Matches(regex) - 必须匹配正则表达式(手机号、密码格式)

# 数组验证
@IsArray() - 必须是数组
@ArrayMinSize(min) - 数组最小长度
@ArrayMaxSize(max) - 数组最大长度

# 其他
@IsIn(values: any[]) - 必须在指定值列表中
@IsNotIn(values: any[]) - 不能在指定值列表中

class-transformer 转换器

shell
# 引入
import { Expose, Transform, Type } from 'class-transformer';

# @Expose() - 使属性包含在转换过程中(会被暴露,建议给所有字段加上@Expose() )
@Expose()
name: string;

# @Exclude() - 排除属性,不参与转换。(使用场景:对于敏感数据使用 @Exclude())
@Exclude()
password: string;

# @Type() - 指定嵌套对象的类型,用于正确的转换。或者强制转换类型(使用场景:始终为嵌套对象使用 @Type() 装饰器)
@Type(() => Photo)
photos: Photo[];

# @Transform() - 自定义转换逻辑。
@Transform(({ value }) => new Date(value))
endDate: Date;

DTO验证&转换

  1. 安装 class-validator class-transformer 插件

    class-validator 用于对 request 参数进行 校验

    class-transformer 用于对 request 参数进行 转换

shell
npm install class-validator class-transformer
  1. 在 src/main.ts 中借助 nestjs 提供的内置 ValidationPipe 管道启用全局管道
ts
import { ValidationPipe } from '@nestjs/common';
// 启用全局验证管道
app.useGlobalPipes(
  new ValidationPipe({
    whitelist: true, // 自动删除非白名单属性
    forbidNonWhitelisted: true, // 如果有非白名单属性,抛出错误
    transform: true, // 自动类型转换
  })
);
  1. 在 DTO 文件中使用 class-validator 验证装饰器,class-transformer 转换装饰器
ts
import { IsString, IsInt, IsEmail, IsNotEmpty, Min, Max, IsOptional } from 'class-validator';
import { Expose, Transform, Type } from 'class-transformer';

export class CreateClassuserDto {
  @Expose() // 别名映射,可不加
  @Transform(({ value }) => value.trim()) // 转换值
  @IsString()
  @IsNotEmpty()
  className: string;

  @Expose()
  @Type(() => Number) // 确保转换为 number 数字
  @IsInt()
  @Min(18)
  @Max(100)
  classAge: number;

  @Expose()
  @IsEmail()
  classEmail: string;

  @IsString()
  @IsOptional()
  classAddress?: string;
}
  1. 在控制器方法中使用这个 DTO
shell
import { CreateClassuserDto } from './dto/create-classuser.dto';
@Post()
create(@Body() createClassuserDto: CreateClassuserDto) {
   return this.classuserService.create(createClassuserDto);
}