经GenerateSchema添加的类在Swagger UI显示但未写入swagger.json
问题背景
- 项目基于ASP.NET Core C#开发,包含控制器与Web API方法,集成Swagger实现接口测试、输出
swagger.json文件,前端所需的类型定义通过NSwag Studio基于该swagger.json自动生成。 - 需求为向
swagger.json中显式添加一批未被任何Web API端点引用的类定义,这些类是项目通过SignalR发送给前端使用的业务类型。 - 现有实现通过自定义
IDocumentFilter,在过滤器中调用context.SchemaGenerator.GenerateSchema()方法添加额外类型,操作后这些类可在Swagger UI(访问地址https://localhost:7103/swagger/index.html)正常展示,但不会出现在最终生成的swagger.json文件中;更换为RegisterType()方法尝试后结果完全一致。 - 现有核心实现代码如下:
// 服务注册阶段 services.AddSwaggerGen(options => { // 其他Swagger配置... options.DocumentFilter<AdditionalSchemasDocumentFilter>(); // 其他Swagger配置... }); // 自定义文档过滤器 public class AdditionalSchemasDocumentFilter : IDocumentFilter { public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { // 现有添加schema的逻辑 context.SchemaGenerator.GenerateSchema(typeof(Notification), context.SchemaRepository); } } // 中间件配置阶段 app.UseSwagger(); app.UseSwaggerUI(c => { c.SwaggerEndpoint($"/swagger/v1/swagger.json", "BackOffice API"); // 其他UI配置... });
问题原因
直接调用GenerateSchema或RegisterType方法,只会将生成的schema存入SchemaRepository的内部缓存,不会自动挂载到当前OpenApiDocument对象的Components.Schemas集合下。SwaggerUI运行时会直接读取SchemaRepository的全量缓存做渲染,因此可以看到新增的类型;但输出swagger.json时,序列化器只会序列化OpenApiDocument对象自身挂载的内容,未挂载到Components.Schemas的schema不会被写入最终的json文件。
可行解决方案
修改自定义AdditionalSchemasDocumentFilter的实现逻辑,生成schema后显式将其挂载到文档的Components.Schemas集合中,同时补全所有依赖的嵌套类型,参考实现如下:
public class AdditionalSchemasDocumentFilter : IDocumentFilter { // 配置所有需要额外加入swagger.json的顶层SignalR类型 private readonly Type[] _extraSignalRTypes = new Type[] { typeof(Notification), // 在此处追加其他需要暴露的类型,例如typeof(ChatMessage), typeof(SystemAlert)等 }; public void Apply(OpenApiDocument swaggerDoc, DocumentFilterContext context) { // 先生成所有顶层类型的schema,生成过程会自动递归生成所有依赖的嵌套类型 foreach (var type in _extraSignalRTypes) { context.SchemaGenerator.GenerateSchema(type, context.SchemaRepository); } // 将SchemaRepository中所有未挂载到文档的schema全量加入Components.Schemas foreach (var (schemaId, schema) in context.SchemaRepository.Schemas) { if (!swaggerDoc.Components.Schemas.ContainsKey(schemaId)) { swaggerDoc.Components.Schemas.Add(schemaId, schema); } } } }
注意事项
- 上述实现会自动递归处理所有顶层类型依赖的嵌套自定义类型,不需要手动枚举所有嵌套类。
- 配置完成后重启应用,直接访问
/swagger/v1/swagger.json即可在components.schemas节点下看到所有新增的类型定义,NSwag Studio读取该json文件可正常生成对应的前端类型代码。 - 不需要额外调用
RegisterType方法,上述逻辑已经覆盖schema生成、挂载的全流程。
内容的提问来源于stack exchange,提问作者Geoff Olding
相关产品推荐
相关产品推荐

