我们正在使用 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 服务版本的发布。