如何在NestJS中将Prisma数据模型映射为不含Token字段的DTO?
解决NestJS返回用户数据时移除Token等多余字段的方案
你遇到的问题是plainToClass默认不会自动剔除原始对象的多余属性,再加上可能未正确处理异步查询结果,导致返回数据包含Token等不必要字段。以下是几种可行的解决方法:
方法一:配置class-transformer并通过装饰器明确字段
通过class-transformer的装饰器标记需要保留的字段,同时开启移除多余属性的配置:
- 确保安装class-transformer:
npm install class-transformer
- 修改
UserDto,用装饰器明确保留字段:
import { Exclude, Expose } from 'class-transformer'; @Exclude() // 默认排除所有未标记@Expose的字段 export class UserDto { @Expose() id: string; @Expose() firstName: string; @Expose() lastName: string; @Expose() email: string; @Expose() nationalityCode: string; @Expose() countryCode: string; @Expose() contactNumber: string; @Expose() passportNumber?: string; @Expose() nicNumber?: string; @Expose() dateOfBirth?: Date; @Expose() profilePictureKey?: string; @Expose() preferredLocaleId: string; }
- 修正服务层代码,await异步查询结果并添加配置:
import { plainToClass } from 'class-transformer'; async getUserById(id: string) { // Prisma查询是异步的,必须await获取结果 const user = await this.userRepository.getUser(id); // 开启excludeExtraneousValues移除多余属性 return plainToClass(UserDto, user, { excludeExtraneousValues: true }); }
方法二:直接在Prisma查询时指定返回字段(性能最优)
从数据库查询阶段就只获取需要的字段,避免后续转换操作:
修改userRepository.getUser方法,使用Prisma的select选项:
// userRepository.ts async getUser(id: string) { return this.prisma.user.findUnique({ where: { id }, select: { id: true, firstName: true, lastName: true, email: true, nationalityCode: true, countryCode: true, contactNumber: true, passportNumber: true, nicNumber: true, dateOfBirth: true, profilePictureKey: true, preferredLocaleId: true, }, }); }
这种方式返回的对象本身就没有Token等多余字段,无需再用plainToClass转换。
方法三:使用NestJS的ClassSerializerInterceptor(优雅方案)
结合NestJS拦截器自动处理DTO转换,无需手动调用plainToClass:
- 在控制器上添加拦截器:
import { Controller, Get, Param, UseInterceptors } from '@nestjs/common'; import { ClassSerializerInterceptor } from '@nestjs/common'; import { UserDto } from './dto/user.dto'; @Controller('users') @UseInterceptors(ClassSerializerInterceptor) // 可全局或控制器级别配置 export class UsersController { constructor(private readonly userService: UsersService) {} @Get(':id') async getUser(@Param('id') id: string): Promise<UserDto> { // 直接返回用户对象,拦截器会自动转换为UserDto格式 return this.userService.getUser(id); } }
- 同样需要给
UserDto添加@Exclude()和@Expose()装饰器(同方法一的Dto代码)。
内容的提问来源于stack exchange,提问作者shehanpathi
相关产品推荐
相关产品推荐

