quarkusio / quarkus

Quarkus: Supersonic Subatomic Java.
https://quarkus.io
Apache License 2.0
13.84k stars 2.7k forks source link

OpenAPI Extension Fails to Generate Schema for Generic Type that Uses Jackson JsonUnwrapped #44627

Open gilday opened 3 days ago

gilday commented 3 days ago

Describe the bug

The Quarkus OpenAPI extension generates incorrect schema for generic Java types that use the Jackson JsonUnwrapped annotation.

smallrye-open-api recognizes Jackson's JsonUnwrapped annotation when generating schema objects (see https://github.com/smallrye/smallrye-open-api/pull/677/files).

Yet, something goes wrong when the annotated property is a parameterized type.

Expected behavior

The JsonUnwrapped annotation is on the property entity of type T. The resource method sets this type parameter to Greeting<LanguageAlternatives>>

record TimestampedEntity<T>(@JsonUnwrapped T entity, Instant timestamp) {}

record Greeting<T extends Alternative>(String message, T alternatives) {}

interface Alternative {}

record LanguageAlternatives(
    @Schema(required = true, example = "Hola") String spanish,
    @Schema(required = true, example = "Hallo") String german)
    implements Alternative {}

  /** In this case, the {@link TimestampedEntity#entity()} property is not unwrapped as expected. */
  @GET
  @Path("/unwrapped-not-handled")
  @Produces(MediaType.APPLICATION_JSON)
  public TimestampedEntity<Greeting<LanguageAlternatives>> greeting() {
    return new TimestampedEntity<>(
        new Greeting<>("hello", new LanguageAlternatives("Hola", "Hallo")), Instant.now());
  }

Expected the schema of the response from this endpoint to look like:

    TimestampedEntityGreetingLanguageAlternatives:
      type: object
      properties:
        alternatives:
          $ref: "#/components/schemas/Alternative"
        message:
          type: string
        timestamp:
          $ref: "#/components/schemas/Instant"

Actual behavior

Because, the extension does not respect the JsonUnwrapped annotation, so the message and alternatives are nested in the entity property that shouldn't exist.

    TimestampedEntityGreetingLanguageAlternatives:
      type: object
      properties:
        entity:
          $ref: "#/components/schemas/GreetingLanguageAlternatives"
        timestamp:
          $ref: "#/components/schemas/Instant"

Note there is another case in the GreetingResource class that causes the schema generation to fail in a slightly different way.

How to Reproduce?

The attached project builds the attached OpenAPI document. The comments in GreetingResource describe the use cases that do not work as expected.

quarkus-openapi-generics.openapi.yml.zip quarkus-openapi-generics.zip

Output of uname -a or ver

Darwin pixee-mbp-gilday.localdomain 24.0.0 Darwin Kernel Version 24.0.0: Tue Sep 24 23:39:07 PDT 2024; root:xnu-11215.1.12~1/RELEASE_ARM64_T6000 arm64

Output of java -version

openjdk version "21.0.3" 2024-04-16 LTS OpenJDK Runtime Environment Temurin-21.0.3+9 (build 21.0.3+9-LTS) OpenJDK 64-Bit Server VM Temurin-21.0.3+9 (build 21.0.3+9-LTS, mixed mode)

Quarkus version or git rev

3.16.4

Build tool (ie. output of mvnw --version or gradlew --version)

Apache Maven 3.9.9 (8e8579a9e76f7d015ee5ec7bfcdc97d260186937) Maven home: /Users/jgilday/.m2/wrapper/dists/apache-maven-3.9.9-bin/33b4b2b4/apache-maven-3.9.9 Java version: 21.0.3, vendor: Eclipse Adoptium, runtime: /Library/Java/JavaVirtualMachines/temurin-21.jdk/Contents/Home Default locale: en_US, platform encoding: UTF-8 OS name: "mac os x", version: "15.0.1", arch: "aarch64", family: "mac"

Additional information

No response

quarkus-bot[bot] commented 3 days ago

/cc @EricWittmann (openapi), @MikeEdgar (openapi), @geoand (jackson), @gsmet (jackson), @mariofusco (jackson), @phillip-kruger (openapi)