springfox-enum-plugin icon indicating copy to clipboard operation
springfox-enum-plugin copied to clipboard

Enum as field in class doesn't show description

Open mkczyk opened this issue 5 years ago • 4 comments

What works

Enum directly in the controller.

public enum SomeEnum {
	@ApiEnum("First Option")
	A, //
	@ApiEnum("Second Option")
	B, //
	C
}
    @PostMapping("/some")
    public void someMethod(@ApiParam("Some description.") SomeEnum param) {}

It shows properly:

Some description.

A: First Option
B: Second Option
C: @ApiEnum annotation not available
Available values : A, B, C

image

What doesn't work

Enum nested in class.

SomeEnum the same as above.

public class ParamParent {
    @ApiModelProperty("Some description.")
    SomeEnum attribute;
}
@PostMapping("/some2")
    public void someMethod2(@RequestParam ParamParent param) {}

It didn't show details of enum:

image

What I tried (but it still doesn't work)

  • Add @ApiModel to class ParamParent,
  • Add @ApiParam to parameter in controller's method: someMethod2(@ApiParam ParamParent param),
  • Add or remove @RequestParam to parameter in controller's method: someMethod2(@RequestParam ParamParent param).

mkczyk avatar Nov 21 '20 17:11 mkczyk

Is the API actually working as expected? I thought you can only use primitive data types as request parameters.

hoereth avatar Nov 21 '20 18:11 hoereth

In the simply example above API doesn't works as expected (I focused only about if Swagger shows documentation of enums).

In Spring controllers you can use classes as parameter (for example: https://spring.io/guides/tutorials/rest/ - you need @RestController or @RequestBody). With enums as fields in class there is one more thing needed (@JsonCreator for decoding string to enum - https://stackoverflow.com/questions/33637427/spring-requestbody-and-enum-value).

Below is fully working API:

@Data
@NoArgsConstructor
@AllArgsConstructor
public class ParamParent {

    @ApiModelProperty("Some description.")
    private SomeEnum attribute;
}
public enum SomeEnum {

    @ApiEnum("First Option")
    A("A"),
    @ApiEnum("Second Option")
    B("B"),
    C("C");

    @JsonValue
    String value;

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

    @JsonCreator
    public static SomeEnum decode(final String code) {
        return Stream.of(SomeEnum.values())
                .filter(targetEnum -> targetEnum.value.equals(code))
                .findFirst()
                .orElse(null);
    }
}
@RequiredArgsConstructor
@RestController
@RequestMapping("/api/tess/")
public class MyController {

    @PostMapping("/some")
    public String someMethod(@ApiParam("Some description.") @RequestParam SomeEnum param) {
        return "Param is: " + param;
    }

    @PostMapping("/some2")
    public String someMethod2(ParamParent param) {
        return "Param attribute is: " + param.getAttribute();
    }

}

API working as expected and what Swagger shows: image

On the left: method with enum directly in controller shows documentation of enums. On the right: method with enum as field in class doesn't show documentation of enums.

mkczyk avatar Nov 21 '20 19:11 mkczyk

Please have a close look at the parameters in your screenshots. They are both annotated with „(query)“, which means it is about GET query parameters. And those parameters can only handle primitive data types. You should mark your object with @RequestBody if you expect a full JSON structure within the post data.

hoereth avatar Nov 22 '20 07:11 hoereth

But I guess @JsonCreator is just not compatible with @ApiEnum.

hoereth avatar Nov 22 '20 07:11 hoereth