Nest框架非控制器层数据转换:Transformer/Mapper/Normalizer选型
在Nest里处理这种数据结构裁剪、字段重命名的需求,有几种靠谱的实现方式,完全可以脱离控制器层,下面逐个讲清楚:
1. 纯Transformer类(user.transformer.ts)
适合逻辑简单、无外部依赖的场景,轻量且不需要注入,直接写纯转换逻辑即可。
代码示例:
// src/users/transformers/user.transformer.ts export class UserTransformer { static toResponse(user: Record<string, any>): { id: number; name: string; email: string } { return { id: user.id, name: user.username, email: user.email }; } }
使用时,不管是在Service还是其他业务层代码里,直接调用UserTransformer.toResponse(rawUser)就行,完全和控制器解耦。
2. Transformer Service(user-transformer.service.ts)
如果后续转换逻辑可能变得复杂(比如需要调用其他服务获取额外数据、处理业务规则),就用Service——它属于Nest的依赖注入体系,能注入其他Service、Repository等资源。
代码示例:
// src/users/services/user-transformer.service.ts import { Injectable } from '@nestjs/common'; @Injectable() export class UserTransformerService { transformToResponse(user: Record<string, any>): { id: number; name: string; email: string } { // 后续可扩展:注入其他服务补充转换逻辑,比如查用户关联角色 return { id: user.id, name: user.username, email: user.email }; } }
使用时在需要的类中注入这个Service:
// 比如在UserService里 import { Injectable } from '@nestjs/common'; import { UserTransformerService } from './user-transformer.service'; @Injectable() export class UserService { constructor(private readonly transformer: UserTransformerService) {} async getUser(id: number) { const rawUser = await this.userRepository.findOneBy({ id }); return this.transformer.transformToResponse(rawUser); } }
3. 用class-transformer实现Mapper
这是Nest生态里非常常用的方式,通过装饰器定义DTO的转换规则,结构清晰,还能配合class-validator做校验,适合结构化的数据转换场景。
首先安装依赖:npm install class-transformer
然后定义响应DTO:
// src/users/dtos/user-response.dto.ts import { Expose, Transform } from 'class-transformer'; export class UserResponseDto { @Expose() id: number; @Transform(({ obj }) => obj.username) @Expose() name: string; @Expose() email: string; }
在业务层使用plainToInstance方法完成转换:
import { plainToInstance } from 'class-transformer'; import { UserResponseDto } from '../dtos/user-response.dto'; // 转换逻辑 const transformedUser = plainToInstance(UserResponseDto, rawUser, { excludeExtraneousValues: true // 自动剔除未用@Expose标注的字段 });
选型建议
- 逻辑简单无依赖:选纯Transformer类,最轻便
- 逻辑复杂需要依赖其他服务:选Transformer Service,符合Nest的DI规范
- 追求结构化、可扩展(比如后续要加校验、更多转换规则):选class-transformer的Mapper方式
内容的提问来源于stack exchange,提问作者eugenedrvnk
相关产品推荐
相关产品推荐

