结构化验证 DTO
DTO 种类
- 响应 DTO:不仅用于请求校验,也可规范接口返回的数据格式(如隐藏敏感字段);
- 查询参数 DTO:配合 @Query() 校验 URL 查询参数(如分页参数 page/size);
- 嵌套 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验证&转换
- 安装 class-validator class-transformer 插件
class-validator 用于对 request 参数进行 校验
class-transformer 用于对 request 参数进行 转换
shell
npm install class-validator class-transformer- 在 src/main.ts 中借助 nestjs 提供的内置 ValidationPipe 管道启用全局管道
ts
import { ValidationPipe } from '@nestjs/common';
// 启用全局验证管道
app.useGlobalPipes(
new ValidationPipe({
whitelist: true, // 自动删除非白名单属性
forbidNonWhitelisted: true, // 如果有非白名单属性,抛出错误
transform: true, // 自动类型转换
})
);- 在 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;
}- 在控制器方法中使用这个 DTO
shell
import { CreateClassuserDto } from './dto/create-classuser.dto';
@Post()
create(@Body() createClassuserDto: CreateClassuserDto) {
return this.classuserService.create(createClassuserDto);
}