springdoc / springdoc-openapi

Library for OpenAPI 3 with spring-boot

Home Page:https://springdoc.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

PolymorphicModelConverter only handles direct subtypes and misses indirect.

aykborstelmann opened this issue · comments

Describe the bug

For a polymorphic api with 3 hierarchy levels (super, intermediate and child) the oneOfs for super are only generated for intermediate and not for child.

To Reproduce
Assume the following api model.

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "@type")
@JsonSubTypes({
  @Type(value = IntermediateClass.class, name = IntermediateClass.SCHEMA_NAME),
})
public sealed class Superclass permits IntermediateClass {

  public Superclass() {}
}

@Schema(name = IntermediateClass.SCHEMA_NAME)
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "@type")
@JsonSubTypes({
  @Type(value = FirstChildClass.class, name = FirstChildClass.SCHEMA_NAME),
  @Type(value = SecondChildClass.class, name = SecondChildClass.SCHEMA_NAME)
})
public sealed class IntermediateClass extends Superclass permits FirstChildClass, SecondChildClass {

  public static final String SCHEMA_NAME = "IntermediateClass";
}

@Schema(name = FirstChildClass.SCHEMA_NAME)
public final class FirstChildClass extends IntermediateClass {

  public static final String SCHEMA_NAME = "Image";
}

@Schema(name = SecondChildClass.SCHEMA_NAME)
public final class SecondChildClass extends IntermediateClass {

  public static final String SCHEMA_NAME = "Mail";
}

AFAIU the correct @JsonSubTypes annotations (w.r.t. spring doc) only include subtypes for the direct subclass (Correct me if I am wrong).
However with this hierarchy if we have a spring controller with Superclass as response type, the generated oneOf statement in the yaml looks the following:

oneOf:
- $ref: '#/components/schemas/Superclass'
- $ref: '#/components/schemas/IntermediateClass'

However, one would expect (and e.g. our frontend generator otherwise produces wrong clients)

oneOf:
- $ref: '#/components/schemas/Superclass'
- $ref: '#/components/schemas/IntermediateClass'
- $ref: '#/components/schemas/FirstChildClass'
- $ref: '#/components/schemas/SecondChildClass'

What version of spring-boot you are using: 3.2.5
What modules and versions of springdoc-openapi are you using: 2.5.0 [springdoc-openapi-starter-common, springdoc-openapi-starter-webmvc-api and springdoc-openapi-starter-webmvc-ui]

If you agree with me that this would be the correct mapping, I offer to create a PR and fix it myself.
My solution proposal would be to extend the PolymorphicModelConverter to also search for subtypes of subtypes recursivly (or rather iteratively).