简体   繁体   中英

How can @JsonValue be used for Swagger enum values using springdoc-openapi with a Lombok getter

Given a Spring Boot project that uses the springdoc-openapi library to expose an OpenAPI (Swagger) endpoint documenting the Spring MVC controller endpoints of the project.

One of the enums in the project uses @JsonValue from Jackson on a field to change the JSON representation of the enum. This enum field is exposed as a getter using the @Getter annotation from Project Lombok :

@Getter
public enum Suit {
    HEARTS("Hearts"), DIAMONDS("Diamonds"), CLUBS("Clubs"), SPADES("Spades");

    @JsonValue
    private final String name;

    Suit(String name) { this.name = name; }
}

However, despite the Jackson representation being based on the field, the enum representation returned by the OpenAPI endpoint uses the toString value of the enum instead:

"suit": {
  "type": "string",
  "enum": [
    "HEARTS",
    "DIAMONDS",
    "CLUBS",
    "SPADES"
  ]
}

Expected:

"suit": {
  "type": "string",
  "enum": [
    "Hearts",
    "Diamonds",
    "Clubs",
    "Spades"
  ]
}

Based on springdoc-openapi#1244 and swagger-core#3998 , it's clear that the @JsonValue annotation needs to be applied to the method, and not the field. However, neither the above attempted approach, nor the following, work:

@Getter @JsonValue
public enum Suit {
    HEARTS("Hearts"), DIAMONDS("Diamonds"), CLUBS("Clubs"), SPADES("Spades");

    private final String name;

    Suit(String name) { this.name = name; }
}

How can this enum be exposed with the proper values in Swagger, while still using Lombok to generate the getter?

The solution is to tell Lombok to use the annotation on the generated getter method, using @Getter(onMethod_ = @JsonValue) on the field.

public enum Suit {
    HEARTS("Hearts"), DIAMONDS("Diamonds"), CLUBS("Clubs"), SPADES("Spades");

    @Getter(onMethod_ = @JsonValue)
    private final String name;

    Suit(String name) { this.name = name; }
}

The onMethod property is documented in the @Getter and @Setter and the onX documentation:

To put annotations on the generated method, you can use onMethod=@__({@AnnotationsHere}) . […] For more details see the documentation on the onX feature.

The syntax is a little strange and depends on the javac you are using.
On javac7, to use any of the 3 onX features, you must wrap the annotations to be applied to the constructor / method / parameter in @__(@AnnotationGoesHere) . To apply multiple annotations, use @__({@Annotation1, @Annotation2}) . The annotations can themselves obviously have parameters as well.
On javac8 and up, you add an underscore after onMethod , onParam , or onConstructor .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM