ASP.NET Core嵌套IEnumerable<int>生成无效OpenAPI JSON文档问题
ASP.NET Core OpenAPI 生成异常问题解决
问题场景
在ASP.NET Core API应用中使用微软内置OpenAPI原生支持时,遇到JSON文档生成异常。相关代码及异常情况如下:
定义的类型
public class MsgMovimentacaoLocaisTrabalho { public IList<InfoGeral>? LocaisRemover { get; set; } public InfoGeral? LocaisAssociar { get; set; } } public class InfoGeral { public Guid GuidDirecao { get; set; } public IEnumerable<int> Locais { get; set; } = Enumerable.Empty<int>(); }
控制器方法
public async Task<IActionResult> MovimentaLocaisTrabalhoAsync( [Description("Mensagem que ....")]MsgMovimentacaoLocaisTrabalho msg, CancellationToken cancellationToken) { ... }
生成的异常OpenAPI JSON片段
... "MsgMovimentacaoLocaisTrabalho": { "type": "object", "properties": { "locaisRemover": { "type": "array", "items": { "$ref": "#/components/schemas/InfoGeral" }, "nullable": true }, "locaisAssociar": { "$ref": "#/components/schemas/InfoGeral2" } } }, "InfoGeral": { "type": "object", "properties": { "guidDirecao": { "type": "string", "format": "uuid" }, "locais": { "type": "array", "items": { "type": "integer", "format": "int32" } } } }, .... "InfoGeral2": { "type": "object", "properties": { "guidDirecao": { "type": "string", "format": "uuid" }, "locais": { "$ref": "#/components/schemas/#/properties/locaisRemover/items/properties/locais" } }, "nullable": true },
语义错误提示
Semantic error at components.schemas.InfoGeral2.properties.locais.$ref
$ref values must be RFC3986-compliant percent-encoded URIs
Jump to line 11623
问题解答
1. 能否让两个属性复用InfoGeral Schema?
可以。该问题是ASP.NET Core OpenAPI生成器处理可空引用类型时的bug导致的重复Schema生成,可通过以下方式解决:
- 显式指定Schema名称:给
InfoGeral类添加特性固定Schema名称,避免生成重复的InfoGeral2:[JsonSchema(Name = "InfoGeral")] public class InfoGeral { // 原有代码 } - 升级框架版本:该bug在.NET 6后续补丁、.NET 7及以上版本中已修复,升级框架可直接解决问题。
- 自定义Schema过滤器:实现
ISchemaFilter,在生成Schema时强制将可空InfoGeral类型指向已有的InfoGeralSchema。
2. 为何locais未生成数组类型,反而出现错误的$ref?
这也是OpenAPI生成器的bug导致的:
生成可空InfoGeral(即InfoGeral?)时,生成器错误尝试复用LocaisRemover中InfoGeral的locais属性引用,但拼接的$ref路径格式错误(重复了#/components/schemas/前缀),违反RFC3986规范。
正常情况下IEnumerable<int>应被解析为array类型(items为int32),这在InfoGeral的Schema中是正确的,仅错误生成的InfoGeral2出现异常。解决重复Schema问题后,该错误引用会消失,locais会正确生成数组类型。
内容的提问来源于stack exchange,提问作者Luis Abreu
相关产品推荐
相关产品推荐

