NestJs中如何为不同端点隐藏同一DTO的特定Swagger属性
解决方案:NestJS 同一 DTO 为不同端点展示不同属性
针对你遇到的问题,目前没有直接在@Body()装饰器层面排除属性的Swagger装饰器,但可以通过以下几种方案实现需求:
方案1:使用@ApiBody()自定义请求体Schema
在控制器的每个端点上,通过@ApiBody()装饰器指定该端点需要展示的属性,直接覆盖DTO的默认Swagger配置:
import { ApiBody } from '@nestjs/swagger'; @Controller('users') export class UsersController { // 端点1:使用4个属性 @Patch('/profile') @ApiBody({ schema: { type: 'object', properties: { username: { type: 'string' }, email: { type: 'string' }, avatar: { type: 'string' }, bio: { type: 'string' } }, required: ['username'] // 可选:指定必填属性 } }) updateUserProfile(@Body() updateUserDto: UpdateUserDTO) { // 逻辑处理 } // 端点2:使用2个属性 @Patch('/password') @ApiBody({ schema: { type: 'object', properties: { oldPassword: { type: 'string' }, newPassword: { type: 'string' } }, required: ['oldPassword', 'newPassword'] } }) updateUserPassword(@Body() updateUserDto: UpdateUserDTO) { // 逻辑处理 } }
这种方式不需要修改原DTO,直接在控制器层面定制每个端点的Swagger展示内容。
方案2:基于基础DTO创建子类,通过@ApiHideProperty()控制展示
创建继承自UpdateUserDTO的子类,在子类中给不需要展示的属性添加@ApiHideProperty():
// 基础DTO export class UpdateUserDTO { @ApiProperty() username: string; @ApiProperty() email: string; @ApiProperty() avatar: string; @ApiProperty() bio: string; @ApiProperty() oldPassword: string; @ApiProperty() newPassword: string; } // 用于端点1的子类 export class UpdateUserProfileDTO extends UpdateUserDTO { @ApiHideProperty() oldPassword: never; @ApiHideProperty() newPassword: never; } // 用于端点2的子类 export class UpdateUserPasswordDTO extends UpdateUserDTO { @ApiHideProperty() username: never; @ApiHideProperty() email: never; @ApiHideProperty() avatar: never; @ApiHideProperty() bio: never; }
然后在控制器中使用对应的子类:
@Patch('/profile') updateUserProfile(@Body() updateUserDto: UpdateUserProfileDTO) { // 逻辑处理 } @Patch('/password') updateUserPassword(@Body() updateUserDto: UpdateUserPasswordDTO) { // 逻辑处理 }
方案3:使用NestJS mapped-types的PickType快速生成DTO
NestJS提供的mapped-types工具可以快速从基础DTO中挑选指定属性生成新的DTO,这是官方推荐的简洁方案:
import { PickType } from '@nestjs/mapped-types'; import { ApiProperty } from '@nestjs/swagger'; // 基础DTO export class UpdateUserDTO { @ApiProperty() username: string; @ApiProperty() email: string; @ApiProperty() avatar: string; @ApiProperty() bio: string; @ApiProperty() oldPassword: string; @ApiProperty() newPassword: string; } // 挑选端点1需要的4个属性 export class UpdateUserProfileDTO extends PickType(UpdateUserDTO, [ 'username', 'email', 'avatar', 'bio' ] as const) {} // 挑选端点2需要的2个属性 export class UpdateUserPasswordDTO extends PickType(UpdateUserDTO, [ 'oldPassword', 'newPassword' ] as const) {}
控制器中直接使用这些生成的DTO即可,Swagger会自动展示对应的属性,同时类型检查也能正常工作。
内容的提问来源于stack exchange,提问作者M Nouman
相关产品推荐
相关产品推荐

