使用 springdoc 处理递归模型
Handling recursive models with springdoc
所以我有一个嵌套模型结构,看起来像这样:
public class TagArea {
private List<TagGroup> groups;
... constructors, getters, setters, etc.
}
public class TagGroup {
private String tagName;
private List<TagGroup> subgroups;
... constructors, getters, setters, etc.
}
以及返回所述模型的控制器。但是,生成的 swagger.json 的架构部分如下所示:
{ "components":
{ "schemas": {
"TaxonomyClientMetadata": {
"type": "object", "properties": {
"tagGroups": {"type": "array", "items": {"$ref": "#/components/schemas/TagGroup"}}
}
},
"TagGroup": {
"type": "object", "properties": {
"tagName": {"type": "string"}
}
}
}
}
整个 属性 就...消失了。我希望 TagGroup
对象看起来更像这样:
"TagGroup": {
"type": "object", "properties": {
"tagName": {"type": "string"},
"subgroups": {"type": "array", "items": {"$ref": "#/components/schemas/TagGroup"}}
}
}
事实上,我目前正在从 Springfox pre-3.0(所以 Swagger 2)迁移到带有 OAS3 的 Springdoc,这是我之前使用 Springfox 观察到的行为,并希望再次支持它。
这可能与向 OAS3 的转变有关,但我找不到任何表明该规范不再允许递归类型的资源。由于依赖于稍旧版本的 springboot,我目前也没有使用最新版本的 springdoc(使用 1.4.8)。
仔细研究一下代码,看起来 ModelConverterContextImpl
保留了 processedTypes 的缓存(我认为范围是当前模式),然后在类型完成时将它们添加到映射缓存处理。在这种情况下,我们开始处理 List<TagGroup>
(因此将 List<TagGroup>
添加到 processedTypes 缓存),这需要递归处理内部的模式。在处理TagGroup的时候,我们发现另一个List<TagGroup>
,我们看到它在processedTypes的缓存中,然后从地图缓存中获取它。但是因为我们从未完成对原始 List<TagGroup>
的处理,它还没有被添加到地图缓存中。因此,返回 null,并且 属性 在 ModelResolver
.
中被忽略
您应该添加 @JsonBackReference
jackson 注释,以解决循环引用问题:
springdoc-openapi 建立在 swagger-core 之上,swagger-core 基于 Jackson 库来解析模型模式。
如果您使用以下定义,它将按预期工作:
@Data
public class TagGroup {
private String tagGroupName;
@JsonBackReference
private List<TagGroup> subgroups;
}
所以我有一个嵌套模型结构,看起来像这样:
public class TagArea {
private List<TagGroup> groups;
... constructors, getters, setters, etc.
}
public class TagGroup {
private String tagName;
private List<TagGroup> subgroups;
... constructors, getters, setters, etc.
}
以及返回所述模型的控制器。但是,生成的 swagger.json 的架构部分如下所示:
{ "components":
{ "schemas": {
"TaxonomyClientMetadata": {
"type": "object", "properties": {
"tagGroups": {"type": "array", "items": {"$ref": "#/components/schemas/TagGroup"}}
}
},
"TagGroup": {
"type": "object", "properties": {
"tagName": {"type": "string"}
}
}
}
}
整个 属性 就...消失了。我希望 TagGroup
对象看起来更像这样:
"TagGroup": {
"type": "object", "properties": {
"tagName": {"type": "string"},
"subgroups": {"type": "array", "items": {"$ref": "#/components/schemas/TagGroup"}}
}
}
事实上,我目前正在从 Springfox pre-3.0(所以 Swagger 2)迁移到带有 OAS3 的 Springdoc,这是我之前使用 Springfox 观察到的行为,并希望再次支持它。
这可能与向 OAS3 的转变有关,但我找不到任何表明该规范不再允许递归类型的资源。由于依赖于稍旧版本的 springboot,我目前也没有使用最新版本的 springdoc(使用 1.4.8)。
仔细研究一下代码,看起来 ModelConverterContextImpl
保留了 processedTypes 的缓存(我认为范围是当前模式),然后在类型完成时将它们添加到映射缓存处理。在这种情况下,我们开始处理 List<TagGroup>
(因此将 List<TagGroup>
添加到 processedTypes 缓存),这需要递归处理内部的模式。在处理TagGroup的时候,我们发现另一个List<TagGroup>
,我们看到它在processedTypes的缓存中,然后从地图缓存中获取它。但是因为我们从未完成对原始 List<TagGroup>
的处理,它还没有被添加到地图缓存中。因此,返回 null,并且 属性 在 ModelResolver
.
您应该添加 @JsonBackReference
jackson 注释,以解决循环引用问题:
springdoc-openapi 建立在 swagger-core 之上,swagger-core 基于 Jackson 库来解析模型模式。
如果您使用以下定义,它将按预期工作:
@Data
public class TagGroup {
private String tagGroupName;
@JsonBackReference
private List<TagGroup> subgroups;
}