如何让Microsoft.AspNetCore.OpenApi生成指向基础Schema的$ref而非同类型属性
解决Microsoft.AspNetCore.OpenApi生成无效$ref路径的问题
问题场景
你定义了如下C#记录类型:
public record Response { public ImmutableList<TypeA>? Completes { get; init; } = null; public ImmutableList<TypeA>? Incompletes { get; init; } = null; // 其他类成员 }
使用Microsoft.AspNetCore.OpenApi生成OpenAPI规范时,Incompletes字段的items引用生成了无效路径:
"Response": { "type": "object", "properties": { "Completes": { "type": "array", "items": { "$ref": "#/components/schemas/TypeA" }, "nullable": true }, "Incompletes": { "type": "array", "items": { "$ref": "#/components/schemas/#/properties/Completes/items" }, "nullable": true } } }
该路径包含无效的#标记,导致API网关工具无法识别,期望生成的规范中Incompletes的items直接指向TypeA的Schema:
"Response": { "type": "object", "properties": { "Completes": { "type": "array", "items": { "$ref": "#/components/schemas/TypeA" }, "nullable": true }, "Incompletes": { "type": "array", "items": { "$ref": "#/components/schemas/TypeA" }, "nullable": true } } }
当前Startup.cs仅配置了基础的OpenApi生成:
services.AddOpenApi(ConfigureApiGen);
其中ConfigureApiGen仅做文档名称等简单配置。
解决方案
通过自定义Schema过滤器修正无效的引用路径,步骤如下:
1. 创建自定义Schema过滤器
实现ISchemaFilter接口,遍历Schema属性并修正数组项的引用:
using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; using System.Reflection; public class FixArrayItemReferenceFilter : ISchemaFilter { public void Apply(OpenApiSchema schema, SchemaFilterContext context) { // 仅处理Response类型的Schema if (context.Type != typeof(Response)) return; // 定位Incompletes属性对应的Schema if (schema.Properties.TryGetValue(nameof(Response.Incompletes), out var incompletesSchema) && incompletesSchema.Type == "array") { // 通过反射获取Incompletes属性的元素类型(TypeA) var incompletesProp = context.Type.GetProperty(nameof(Response.Incompletes)); var itemType = incompletesProp?.PropertyType.GetGenericArguments()[0]; if (itemType == null) return; // 生成元素类型对应的Schema ID var schemaId = context.SchemaGenerator.GenerateSchemaId(itemType); // 替换为正确的引用 incompletesSchema.Items.Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = schemaId }; } } }
如果只需要针对TypeA做处理,也可以使用简化版本:
public class FixArrayItemReferenceFilter : ISchemaFilter { public void Apply(OpenApiSchema schema, SchemaFilterContext context) { foreach (var property in schema.Properties.Values) { if (property.Type == "array" && property.Items?.Reference != null) { // 检测到无效内部引用时替换为TypeA的Schema引用 if (property.Items.Reference.Id.Contains("#")) { property.Items.Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = "TypeA" }; } } } } }
2. 注册自定义过滤器
修改ConfigureApiGen方法,添加过滤器注册:
private void ConfigureApiGen(OpenApiGeneratorOptions options) { // 原有文档配置(示例) options.AddDocumentTransformer(doc => { doc.Info.Title = "你的API文档"; doc.Info.Version = "v1"; }); // 注册自定义Schema过滤器 options.SchemaFilter<FixArrayItemReferenceFilter>(); }
原理说明
自定义过滤器会在OpenAPI Schema生成过程中拦截处理,针对Response类型的Incompletes属性,将其数组项的无效内部引用替换为直接指向TypeA的Schema引用,确保生成的OpenAPI规范路径符合标准格式,被API网关工具正常识别。
内容的提问来源于stack exchange,提问作者CodingBeagle
相关产品推荐
相关产品推荐

