如何阻止Swagger展开嵌套的DTO属性
问题描述
在NestJS的GET接口中,使用@Query() query: AnalyticsRequestDTO<G>接收查询参数时,AnalyticsFilterDTO被Swagger自动展开为平级参数,但实际业务要求过滤参数必须包裹在filter对象中(如filter[ruleId]的嵌套格式),导致按Swagger提示发送请求时接口报错。
解决方案
1. 用@ApiNestedProperty标记嵌套对象
在AnalyticsRequestDTO的filter字段上,替换@ApiProperty为@ApiNestedProperty,明确告知Swagger这是嵌套对象,避免自动展开:
import { ApiNestedProperty } from '@nestjs/swagger'; export class AnalyticsRequestDTO< G extends GroupableKeys, P extends PopulateableKeys<G> | undefined = undefined > implements AggregateRunLogAnalyticsOptions<G, P> { @IsObject() @IsOptional() @ApiNestedProperty({ description: 'Filters to apply logs', required: false, type: AnalyticsFilterDTO, }) filter: AnalyticsFilterDTO = {} // 其余字段保持不变 }
2. 配置嵌套查询参数解析
NestJS默认不支持解析filter[ruleId]这类嵌套格式的查询参数,需要通过以下方式处理:
方式A:全局启用隐式转换
在main.ts中配置ValidationPipe时开启enableImplicitConversion,自动处理嵌套参数解析:
import { ValidationPipe } from '@nestjs/common'; async function bootstrap() { const app = await NestFactory.create(AppModule); app.useGlobalPipes(new ValidationPipe({ enableImplicitConversion: true, transform: true, })); await app.listen(3000); } bootstrap();
方式B:自定义管道处理嵌套参数
如果不想全局启用转换,可以创建专属管道解析嵌套查询参数:
import { PipeTransform, Injectable } from '@nestjs/common'; @Injectable() export class ParseNestedQueryPipe implements PipeTransform { transform(value: any) { const parsed = {}; for (const key in value) { const match = key.match(/(\w+)\[(\w+)\]/); if (match) { const [parent, child] = match.slice(1); parsed[parent] = parsed[parent] || {}; parsed[parent][child] = value[key]; } else { parsed[key] = value[key]; } } return parsed; } }
然后在控制器中使用该管道:
@Get('/app/:appId/pages') // 其余装饰器保持不变 public async getPageRuleStatistics<G extends GroupableKeys>( @Param('appId', MongoIdPipe) applicationId: string, @Query(ParseNestedQueryPipe) query: AnalyticsRequestDTO<G>, @Query('forceRebuild', new DefaultValuePipe(false), ParseBoolPipe) forceRebuild = false ): Promise<AnalyticsResultsDTO<G>> { // 方法逻辑保持不变 }
3. 手动指定Swagger Schema(可选)
如果上述方法仍未解决问题,可以手动配置@ApiQuery的schema,强制Swagger显示嵌套结构:
@ApiQuery({ name: 'query', schema: { type: 'object', properties: { filter: { $ref: '#/components/schemas/AnalyticsFilterDTO', }, groupBy: { type: 'array', items: { type: 'string', enum: Object.values(GroupableKeys), }, }, populate: { type: 'array', items: { type: 'string' }, }, }, }, })
完成以上配置后,Swagger会正确展示嵌套的filter对象结构,请求时通过filter[ruleId]、filter[componentType]等格式传递参数,接口就能正确解析为AnalyticsRequestDTO对象。
内容的提问来源于stack exchange,提问作者Aocamilo
相关产品推荐
相关产品推荐

