我们正在使用 MS 为 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>();
}
MsgMovimentacaoLocaisTrabalho
用作控制器方法之一的参数类型:
public async Task<IActionResult> MovimentaLocaisTrabalhoAsync(
[Description("Mensagem que ....")]MsgMovimentacaoLocaisTrabalho msg,
CancellationToken cancellationToken) {
...
问题在于类型的输出:
...
"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
},
首先,查看InfoGeral
架构,它看起来不错(locais
表示为 的数组int
),但我不确定为什么会有类型InfoGeral2
。我假设这是因为该类型MsgMovimentacaoLocaisTrabalho
有 2 个引用该类型的属性...
第一个问题:有没有办法让这两个属性的架构重用InfoGeral
?
问题 2:为什么我最终得到的是错误的值locais
而不是数组?IEnumerable 不应该在架构上生成数组吗?
顺便说一句,这是错误:
Semantic error at components.schemas.InfoGeral2.properties.locais.$ref
$ref values must be RFC3986-compliant percent-encoded URIs
Jump to line 11623
检查此问题:.NET 9 OpenAPI 为同一对象生成大量重复架构
此错误已在 .NET 10 中修复并反向移植到 .NET 9。您将在 .NET 9 的下一个服务版本中找到它。
为什么会发生此错误?问题的关键在于 System.Text.Json 生成的架构(严格遵守 JSON 架构规范)与 OpenAPI.NET 包(JSON 架构的超集)所期望的架构之间的不兼容性。STJ 使用相对引用来捕获递归或重复的类型引用。OpenAPI.NET 不会将这些引用识别为等效的,从而导致重复的架构。
在 .NET 9 中,我们通过向自定义比较器引入逻辑来将相对引用视为与任何生成的类型等效来解决这个问题。
在 .NET 10 中,我们正在升级到新版本的 OpenAPI.NET 包,该包增加了内置支持,能够解析这些相对引用并检测架构模型中的“环回”。
因此,让我们等待下一个.NET 服务版本的发布。