如何将NestJS的reflect metadata注入到Swagger对应字段中
NestJS自定义元数据同步到Swagger实现方案
你可以通过以下两种方案实现将@Rights、@Level等自定义装饰器挂载的元数据展示到Swagger接口文档中,不需要修改现有控制器的业务代码。
方案1:改造自定义装饰器(最简实现,推荐小项目使用)
利用NestJS的applyDecorators工具,将元数据设置逻辑和Swagger注解逻辑组合到同一个自定义装饰器中:
步骤1:改造自定义装饰器
import { SetMetadata, applyDecorators } from '@nestjs/common'; import { ApiExtension } from '@nestjs/swagger'; // 原@Rights装饰器改造 export const Rights = (rights: string) => { return applyDecorators( SetMetadata('rights', rights), // 原有设置元数据的逻辑保留 ApiExtension('x-required-rights', rights) // 新增Swagger扩展字段 ); }; // 原@Level装饰器改造 export const Level = (level: 'read' | 'write') => { return applyDecorators( SetMetadata('level', level), // 原有设置元数据的逻辑保留 ApiExtension('x-required-permission-level', level) // 新增Swagger扩展字段 ); };
步骤2:开启Swagger扩展字段展示
在项目入口文件main.ts的Swagger初始化配置中,开启扩展字段展示:
SwaggerModule.setup('api-doc', app, document, { swaggerOptions: { showExtensions: true // 展示所有自定义扩展字段 } });
配置完成后,所有挂载了@Rights、@Level装饰器的接口,都会在Swagger的接口详情区域自动展示对应的权限要求字段。
方案2:全局自动注入元数据(无侵入,推荐中大型项目使用)
如果你不想修改现有自定义装饰器的代码,可以在Swagger文档生成阶段,通过Reflector全局扫描所有路由的元数据,自动注入到Swagger配置中:
import { NestFactory } from '@nestjs/core'; import { AppModule } from './app.module'; import { DocumentBuilder, SwaggerModule } from '@nestjs/swagger'; import { Reflector } from '@nestjs/core'; async function bootstrap() { const app = await NestFactory.create(AppModule); const reflector = app.get(Reflector); // 基础Swagger配置 const swaggerConfig = new DocumentBuilder() .setTitle('业务接口文档') .setVersion('1.0') .build(); const swaggerDocument = SwaggerModule.createDocument(app, swaggerConfig); // 遍历所有路由,注入自定义元数据到Swagger const serverRoutes = app.getHttpServer()._events.request._router.stack; serverRoutes.forEach(route => { if (!route?.route) return; const { path, stack, methods } = route.route; const handler = stack[0].handle; const requestMethod = Object.keys(methods)[0]; // 读取自定义元数据 const requiredRights = reflector.get('rights', handler); const requiredLevel = reflector.get('level', handler); if (!requiredRights && !requiredLevel) return; // 匹配Swagger文档中的对应接口 const pathItem = swaggerDocument.paths[path]; if (!pathItem || !pathItem[requestMethod]) return; // 注入元数据到Swagger接口配置 const operation = pathItem[requestMethod]; if (requiredRights) operation['x-required-rights'] = requiredRights; if (requiredLevel) operation['x-required-permission-level'] = requiredLevel; }); // 挂载Swagger文档 SwaggerModule.setup('api-doc', app, swaggerDocument, { swaggerOptions: { showExtensions: true } }); await app.listen(3000); } bootstrap();
该方案完全不需要修改现有业务代码和自定义装饰器代码,全局统一处理所有接口的元数据同步逻辑。
内容的提问来源于stack exchange,提问作者Vlad
相关产品推荐
相关产品推荐

