使用 springdoc 处理递归模型

Eat*_*age 3 java openapi 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.
}
Run Code Online (Sandbox Code Playgroud)

以及返回所述模型的控制器。但是,生成的 swagger.json 的架构部分如下所示:

{ "components": 
  { "schemas": {
    "TaxonomyClientMetadata": {
      "type": "object", "properties": {
        "tagGroups": {"type": "array", "items": {"$ref": "#/components/schemas/TagGroup"}}
      }
    }, 
    "TagGroup": {
      "type": "object", "properties": {
        "tagName": {"type": "string"}
      }
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

整个财产就这样……消失了。我希望该TagGroup对象看起来更像这样:

"TagGroup": {
  "type": "object", "properties": {
    "tagName": {"type": "string"},
    "subgroups": {"type": "array", "items": {"$ref": "#/components/schemas/TagGroup"}}
  }
}
Run Code Online (Sandbox Code Playgroud)

事实上,我目前正在从 Springfox 3.0 之前的版本(即 Swagger 2)迁移到带有 OAS3 的 Springdoc,这是我之前在 Springfox 中观察到的行为,并且希望再次支持它。

这可能与向 OAS3 的转变有关,但我找不到任何表明该规范不再允许递归类型的资源。由于依赖于稍旧版本的 springboot,我目前也没有使用最新版本的 springdoc(使用 1.4.8)。

仔细研究一下代码,它看起来像是ModelConverterContextImpl保留了processedTypes的缓存(我认为范围是当前模式),然后在类型处理完成时将它们添加到映射缓存中。在这种情况下,我们开始处理List<TagGroup>(并因此添加List<TagGroup>到processedTypes缓存),这需要递归地处理内部的模式。当处理TagGroup时,我们找到另一个TagGroup List<TagGroup>,我们看到它在processedTypes的缓存中,然后从地图缓存中获取它。但由于我们从未完成对原始 的处理List<TagGroup>,因此它尚未添加到地图缓存中。因此,返回 null,并且该属性在 中被忽略ModelResolver

bri*_*bro 7

您应该添加@JsonBackReferenceJackson 注释,以实现循环引用解析:springdoc-openapi 构建在 swagger-core 之上,它基于 Jackson 库来解析模型架构。

如果您使用以下定义,它将按预期工作:

@Data
public class TagGroup {
    private String tagGroupName;

    @JsonBackReference
    private List<TagGroup> subgroups;

}
Run Code Online (Sandbox Code Playgroud)