So I have a nested model structure that looks something like this:
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.
}
And a controller that is returning said model. However, the schema portion of the swagger.json generated looks like this:
{ "components":
{ "schemas": {
"TaxonomyClientMetadata": {
"type": "object", "properties": {
"tagGroups": {"type": "array", "items": {"$ref": "#/components/schemas/TagGroup"}}
}
},
"TagGroup": {
"type": "object", "properties": {
"tagName": {"type": "string"}
}
}
}
}
An entire property just... gone. I would expect the TagGroup object to look more like this:
"TagGroup": {
"type": "object", "properties": {
"tagName": {"type": "string"},
"subgroups": {"type": "array", "items": {"$ref": "#/components/schemas/TagGroup"}}
}
}
Indeed, I'm currently migrating from Springfox pre-3.0 (so Swagger 2) to Springdoc with OAS3, and this is the behaviour I was previously observing with Springfox, and would like support for it once again.
It's possible this is related to the shift to OAS3, but I couldn't find any resources that suggest the spec no longer allows recursive types. I'm also currently not on the latest of version of springdoc (using 1.4.8) due to a dependency on a slightly older version of springboot.
Digging through the code a bit, it looks like the ModelConverterContextImpl keeps a cache of processedTypes (scoped to the current schema I think), and then adds them to a mapping cache when the type is finished being processed. In this scenario, we start processing the List<TagGroup> (and so add List<TagGroup> to the processedTypes cache), which requires recursively processing the schemas inside. When processing the TagGroup, we find another List<TagGroup>, we see that it's in the cache of processedTypes, then fetch it from the map cache. But because we never finished processing the original List<TagGroup>, it hasn't been added to the map cache. As such, null is returned, and the property gets ignored in ModelResolver.