【NestJS】NestJS三件套:校验、转换与文档生成,对比Django DRF
🚀 NestJS 三件套:class-validator
+ class-transformer
+ @nestjs/swagger
全面解析
一文看懂它们的角色分工、协同逻辑与 DRF 的类比关系
一、🌈 背景:NestJS 为何需要三件套?
在 NestJS 中,我们经常要定义「数据输入输出规范」:
- 用户发来的请求体要验证是否合法(参数校验)
- 验证通过后要转换成业务对象(类型转换)
- 同时希望自动生成接口文档(OpenAPI)
在 Django DRF 中,这一切由 Serializer 一手包办。
但在 NestJS 中,它采用了更“模块化”的设计理念——
把这三个功能拆分成了三个独立库,每个都干一件事,并通过 装饰器(Decorator)联动。
模块 | 作用 | 类比 DRF |
---|---|---|
class-validator | 参数校验(输入验证) | Serializer 的 validate_* / 字段校验 |
class-transformer | plain ↔ class 转换(类型映射) | Serializer.to_internal_value / to_representation |
@nestjs/swagger | 自动生成 OpenAPI 文档 | drf-spectacular / drf-yasg |
二、🔍 各模块角色详解
1️⃣ class-validator
—— 参数守门员
它是 请求数据的验证层,负责判断每个字段是否符合要求。
import { IsString, IsEmail, IsOptional } from 'class-validator';export class CreateUserDto {@IsString()name: string;@IsEmail()email: string;@IsOptional()avatar?: string;
}
-
✅ 验证逻辑完全声明式(装饰器定义规则)
-
✅ 自动与 Nest 的
ValidationPipe
配合使用app.useGlobalPipes(new ValidationPipe({ transform: true }));
-
🚫 如果验证失败,会自动抛出 400 错误
📖 类比 DRF:
就像 DRF 的
Serializer
自动校验字段一样,
class-validator
让 TypeScript 类变成了一个「可验证的 Schema」。
2️⃣ class-transformer
—— 数据翻译官
请求数据(通常是 plain object)需要转成带类型的 DTO 实例,
而响应对象(class 实例)又要转成 plain JSON 输出。
这时就轮到 class-transformer
出场:
import { plainToInstance } from 'class-transformer';const user = plainToInstance(CreateUserDto, {name: 'Alice',email: 'alice@example.com',
});
你甚至可以定义嵌套结构:
class Profile {@IsString()nickname: string;
}class CreateUserDto {@ValidateNested()@Type(() => Profile)profile: Profile;
}
📖 类比 DRF:
它就像 DRF 的
Serializer.to_internal_value()
和to_representation()
,
把数据在 外部(JSON) 和 内部(模型实例) 之间做映射。
3️⃣ @nestjs/swagger
—— 文档自动机
Nest 提供了一个插件式的 Swagger 集成,能自动读取上面两个库的元数据,生成 OpenAPI 文档:
import { ApiProperty } from '@nestjs/swagger';export class CreateUserDto {@ApiProperty({ description: '用户名', example: 'Alice' })@IsString()name: string;
}
启动后访问 /api-docs
,即可看到 Swagger UI。
📖 类比 DRF:
就像 DRF 的
drf-spectacular
或drf-yasg
自动生成接口文档一样,
Nest 的 Swagger 插件通过反射自动扫描 DTO 装饰器信息。
三、⚙️ 三件套联动的魔力
当你在主入口配置了:
app.useGlobalPipes(new ValidationPipe({ transform: true }));
就意味着:
- Nest 拿到请求体(plain object)
- 用
class-transformer
自动转成 DTO 实例 - 用
class-validator
对 DTO 进行验证 - 用
@nestjs/swagger
读取 DTO 装饰器信息生成文档
全部无缝衔接。
🎯 三件套 = 序列化 + 校验 + 文档 三合一
四、🧩 多层嵌套与数组
✅ 对象嵌套
class DeviceInfoDto {@ApiProperty({ example: 'Windows' })@IsString()os: string;
}class LoginDto {@ApiProperty({ type: () => DeviceInfoDto })@ValidateNested()@Type(() => DeviceInfoDto)device: DeviceInfoDto;
}
✅ 数组嵌套
@ApiProperty({ type: () => DeviceInfoDto, isArray: true })
@ValidateNested({ each: true })
@Type(() => DeviceInfoDto)
devices: DeviceInfoDto[];
五、🧬 继承与组合技巧(高级篇)
✅ 基础类继承
export class BaseUserDto {@ApiProperty()@IsString()name: string;
}export class CreateUserDto extends BaseUserDto {@ApiProperty()@IsString()password: string;
}
✅ 使用 @nestjs/mapped-types
动态继承
@nestjs/mapped-types
提供了几个实用的类型继承助手:
工具 | 作用 | 类似 DRF 的 |
---|---|---|
PartialType() | 所有字段变为可选 | Serializer(partial=True) |
PickType() | 只选指定字段 | fields = ['a', 'b'] |
OmitType() | 排除某些字段 | exclude = ['password'] |
IntersectionType() | 多个类合并 | 多继承多个 Serializer |
示例:
import { PartialType, PickType } from '@nestjs/mapped-types';export class UpdateUserDto extends PartialType(CreateUserDto) {}
export class LoginUserDto extends PickType(CreateUserDto, ['name', 'password']) {}
六、🔥 整体总结:三件套如何替代 DRF 的 Serializer
功能 | DRF Serializer | NestJS 三件套 |
---|---|---|
输入校验 | 字段定义 + 验证器 | class-validator |
类型转换 | to_internal_value / to_representation | class-transformer |
自动文档 | drf-spectacular / drf-yasg | @nestjs/swagger |
字段描述 | help_text / label / example | @ApiProperty |
部分更新 | partial=True | PartialType() |
嵌套对象 | NestedSerializer | ValidateNested + Type() |
👉 NestJS 没有“一个类包办所有功能”,而是以更强的模块化 + 装饰器联动实现同样的效果。
七、💡 实战体验:一个 DTO 三重功效
export class RegisterDto {@ApiProperty({ description: '邮箱', example: 'alice@example.com' })@IsEmail()email: string;@ApiProperty({ description: '密码', example: '123456' })@IsString()password: string;
}
- ✅ 自动校验:
ValidationPipe
拦截非法请求 - ✅ 自动类型:plain →
RegisterDto
实例 - ✅ 自动文档:Swagger 展示字段描述与示例
👉 一处定义,三方受益。真正实现 “一次声明,全链通用”。
八、🧭 结语
NestJS 三件套就像一支协调有序的交响乐队:
class-validator
是“守门员”,拦截非法输入;class-transformer
是“翻译官”,连接 plain 与 class;@nestjs/swagger
是“记录员”,把一切自动写进文档。
三者协作的结果就是:
你写的每一个 DTO,既是 Schema,又是 Validator,还是 OpenAPI 文档生成源。
这正是 NestJS 的优雅所在 ——
把数据结构当作一等公民,用装饰器让类型、验证、文档三合一。