Microsoft.AspNetCore.OpenApi生成OpenAPI文档时,同一类中相同类型的第二个列表未生成类型引用
我之前碰到过一模一样的问题!当用ASP.NET Core的OpenAPI生成器处理包含两个同类型列表属性的record时,确实会出现第二个列表的items没有正确引用已有Schema的情况,导致客户端生成工具把它识别成动态对象列表,特别闹心。
先帮你把问题场景再理清楚:你的代码里定义了Balance record,包含两个List<BalanceEntry>属性(Assets和Liabilities),返回这个类型的实例时,生成的OpenAPI文档里只有第一个列表(Assets)的items正确引用了BalanceEntry Schema,第二个列表(Liabilities)的items却是空对象,没有$ref标记,就像你贴的这段:
... "Balance": { "required": [ "assets", "liabilities" ], "type": "object", "properties": { "assets": { "type": "array", "items": { "$ref": "#/components/schemas/BalanceEntry" } }, "liabilities": { "type": "array", "items": { } } } }, ...
这个问题本质是Microsoft.OpenApi(被Microsoft.AspNetCore.OpenApi依赖,你用的是1.6.17版本)在处理重复同类型数组属性时的一个bug——第一个数组属性注册Schema引用后,第二个同类型数组的items类型会被错误地忽略。
给你几个可行的解决办法:
方案1:用Schema过滤器手动补全引用
这是最直接的临时修复方式,通过自定义Schema过滤器,手动给Liabilities的items加上类型引用。在Program.cs里修改OpenAPI的注册代码:
builder.Services.AddOpenApi(options => { options.SchemaFilter<BalanceSchemaFilter>(); }); // 自定义Schema过滤器 public class BalanceSchemaFilter : ISchemaFilter { public void Apply(OpenApiSchema schema, SchemaFilterContext context) { // 只处理Balance类型的Schema if (context.Type != typeof(Balance)) return; // 找到liabilities属性,手动设置它的items引用到BalanceEntry if (schema.Properties.TryGetValue("liabilities", out var liabilitiesSchema)) { liabilitiesSchema.Items.Reference = new OpenApiReference { Type = ReferenceType.Schema, Id = nameof(BalanceEntry) }; } } }
方案2:升级依赖库版本
这个bug在较新的Microsoft.OpenApi版本中已经被修复了。你可以尝试升级Microsoft.AspNetCore.OpenApi到对应.NET版本的最新补丁包(比如.NET 9的话可以更到9.0.8及以上),升级后会自动同步更新依赖的Microsoft.OpenApi库,问题应该就能直接解决。
应用任意一个方案后,生成的OpenAPI文档里Liabilities的items都会正确出现"$ref": "#/components/schemas/BalanceEntry",客户端生成工具就能正确识别为List<BalanceEntry>了。
内容来源于stack exchange

