81n0n4b1bK
81n0n4b1bK

Reputation: 71

How to annotate DTO so that it shows up in SwaggerUI Schema?

I have a controller with a @RequestBody DTO. I need to show the DTO's schema instead of the default string in the RequestBody Schema in Swagger.

By using @Operation above the API and @Parameter within, I've been able to describe the DTO in two places

image-description

and fill in the example (see code). I've tried @Schema in the @Operation (under requestBody) and @Parameter annotations. The former throws an NPE and the latter changes nothing, with a variety of tries regarding counterpart annotations in the DTO itself.

Sample Controller

@RequestMapping(value = "/{myPathVar}", method = RequestMethod.POST)
@Operation(summary = "Create something.", 
    parameters = { @Parameter(in = ParameterIn.PATH, name = "myPathVar", description = "Some path variable. Swagger uses this description.") },             
    requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
        description = "My description here.", 
        content = @Content(examples = @ExampleObject("{\"A\" : \"a\",\"B\" : \"{\"b\" : \"foo\", \"bb\" : \"bar\"}"))))
@ApiResponse(content = @Content(schema = @Schema(implementation = MyReturningType.class)))
public MyReturningType doSomethingCool(
    @Parameter(description = "Some description Swagger ignores.", example = "123") @PathVariable(value = "myPathVar") int myPathVar,
    @Parameter(description = "My other description here.", schema = @Schema(implementation = MyDto.class)) @RequestBody MyDto dto) {
    // do something cool
}

Sample DTO

// Do I need certain annotations here?
public class MyDto {
    // What annotation goes here? @Parameter, @JsonProperty, @Schema, something else?
    private int someInt;
    private String someString;
    private Object someObject;
}

What combination of annotations do I need to correctly label the DTO Schema within the DTO and then reference this Schema from the controller such that the Schema field is populated in SwaggerUI?

Upvotes: 7

Views: 21980

Answers (2)

amit ghosh
amit ghosh

Reputation: 91

Annotated your dto like the following. It works for me

@Schema(description = "User Dto")
@Data
public class UserDto {
  private int id;

  @JsonProperty
  private String email;

  @JsonProperty
  private String password;

  @JsonProperty
  private String firstName;

  @JsonProperty
  @Schema(description = "User Id")
  private String lastName;
}

Screenshot

Upvotes: 1

Debargha Roy
Debargha Roy

Reputation: 2708

The issue might have been caused by the fact that the fields in your DTO are of private visibility and from the code you shared, doesn't look like they have getters and setters available.

Refer to the below example for a working example of how it can be done

Controller

// Using the specific mapping annotation will keep the code clean
@PostMapping("/{myPathVar}")

// The below annotation describes the operation
@Operation(
    summary = "Brief description of the operation",
    description = "Detailed description of the operation")

// Describe the possible responses next. Prefer using @ApiResponses for multiple response
@ApiResponse(

    // specify the http response code
    responseCode = "201",

    // some description. Maybe use the corresponding http response code's description
    description = "Created",

    // describe the content that will be returned for this response code
    content = @Content(
        // optionally, specify the media type for the response here as shown in the below code
         mediaType = MediaType.APPLICATION_JSON_VALUE,
        // specify the implementation of the response DTO here
        schema = @Schema(implementation = Void.class)))

public Void doSomethingCool(

    // Use @Parameter for @PathVariable and @RequestVariable
    @Parameter(description = "Description for path/request-parameter here")
    @PathVariable(value = "myPathVar")
        int myPathVar,

    // Both these @RequestBody annotations are mandatory.
    @io.swagger.v3.oas.annotations.parameters.RequestBody(
        description = "Controller-level model description here")
    @org.springframework.web.bind.annotation.RequestBody
        TestDTO dto) {
  // ... do some cool stuff here
  return null;
}

DTO

@Schema(description = "Model-level description here")
public class TestDTO {

  @Schema(description = "Field-level description here")
  private int someInt;

  @Schema(description = "Another Field-level description here")
  private String someString;

  @Schema(description = "Yet another Field-level description here")
  private Object someObject;

  // all getters and setters here

}

This gives you the output as below

swagger-ui-sample

Upvotes: 4

Related Questions