Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enums with custom representation are not correctly documented in Open API / Swagger UI #25011

Closed
josephearl opened this issue Apr 19, 2022 · 5 comments
Labels
area/swagger-ui kind/bug Something isn't working

Comments

@josephearl
Copy link

josephearl commented Apr 19, 2022

Describe the bug

When serialising enums using something other than their name - either @JsonValue on a enum method like toString, @JsonProperty on the enum constants, or @JsonSerialize(using = SomeSerializer.class) on an enum property - the Open API documentation is incorrect and only uses the enum constant names.

@Path("/api/v1/my")
public class MyController {
  @GET
  @Path("/1")
  public List<MyResponse1> getMyResponse1() {
    return List.of(new MyResponse1(MyEnum1.RED), new MyResponse1(MyEnum1.BLUE), new MyResponse1(MyEnum1.GREEN));
  }

  @GET
  @Path("/2")
  public List<MyResponse2> getMyResponse2() {
    return List.of(new MyResponse2(MyEnum2.RED), new MyResponse2(MyEnum2.BLUE), new MyResponse2(MyEnum2.GREEN));
  }

  @GET
  @Path("/3")
  public List<MyResponse3> getMyResponse3() {
    return List.of(new MyResponse3(MyEnum3.RED), new MyResponse3(MyEnum3.BLUE), new MyResponse3(MyEnum3.GREEN));
  }
}

enum MyEnum1 {
  RED("r"),
  GREEN("g"),
  BLUE("b");

  private final String value;

  MyEnum1(String value) {
    this.value = value;
  }

  @Override
  @JsonValue
  public String toString() {
    return value;
  }
}

class MyResponse1 {
  private final MyEnum1 myEnum1;

  public MyResponse1(MyEnum1 myEnum1) {
    this.myEnum1 = myEnum1;
  }

  public MyEnum1 getMyEnum1() {
    return myEnum1;
  }
}

enum MyEnum2 {
  @JsonProperty("r") RED,
  @JsonProperty("g") GREEN,
  @JsonProperty("b") BLUE;
}

class MyResponse2 {
  private final MyEnum2 myEnum2;

  public MyResponse2(MyEnum2 myEnum2) {
    this.myEnum2 = myEnum2;
  }

  public MyEnum2 getMyEnum2() {
    return myEnum2;
  }
}

enum MyEnum3 {
  RED("r"),
  GREEN("g"),
  BLUE("b");

  private final String value;

  MyEnum3(String value) {
    this.value = value;
  }

  @Override
  public String toString() {
    return value;
  }
}

class MyResponse3 {
  private final MyEnum3 myEnum3;

  public MyResponse3(MyEnum3 myEnum3) {
    this.myEnum3 = myEnum3;
  }

  @JsonSerialize(using = ToStringSerializer.class)
  public MyEnum3 getMyEnum3() {
    return myEnum3;
  }
}

In all 3 cases the correct values are returned when calling the API.

Adding @Schema(enumeration = {"r", "g", "b"}) to the declaration of one of the enums results in the correct result for that enum.

However if the enum source is not under my control (e.g. in case 3 using a custom serializer), then I cannot do this - I tried adding the same annotation to the enum property in the response class instead, but this results in the values being added to the existing enum names (resulting in [ RED, GREEN, BLUE, r, g, b ]).

Expected behavior

I expected that enum values which do not use a custom serializer (case 1 and 2) under my source control are correctly documented without additional

Additionally, I would expected that enum values which use a custom serializer (case 3) and are not under my source control can be correctly documented in Open API (using annotations like @Schema if necessary).

Actual behavior

No response

How to Reproduce?

No response

Output of uname -a or ver

macOS 12.3.1

Output of java -version

17.0.2

GraalVM version (if different from Java)

No response

Quarkus version or git rev

2.8.0.Final

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

Gradle 7.4.2

Additional information

No response

@josephearl josephearl added the kind/bug Something isn't working label Apr 19, 2022
@quarkus-bot
Copy link

quarkus-bot bot commented Apr 19, 2022

/cc @MikeEdgar, @phillip-kruger

@MikeEdgar
Copy link
Contributor

@josephearl - we do have support for @JsonValue, which appears to not be working here. Do you see any examples in the logs with something like

Failed to read enumeration values from enum MyEnum1 method toString with `@JsonValue`: <exception>

@josephearl
Copy link
Author

josephearl commented Apr 19, 2022

@MikeEdgar yes I do

SROAP02016: Failed to read enumeration values from enum com.example.MyResponse1$MyEnum1 method toString with `@JsonValue`: java.lang.IllegalAccessException: class io.smallrye.openapi.runtime.io.schema.SchemaFactory cannot access a member of class com.example.MyResponse1$MyEnum1 with modifiers "public"

do you know why (and how to fix it)?

@MikeEdgar
Copy link
Contributor

Are your enums package private? Do you have the option to make them public?

@josephearl
Copy link
Author

josephearl commented Apr 22, 2022

@MikeEdgar they were, making them public fixed it, thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/swagger-ui kind/bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants