Reputation: 1429
I was generating Swagger API specification from Spring Boot REST controllers using Springfox.
I noticed an issue where the example value/model could not be shown for response.
As an investigation, I checked the JSON API doc at http://localhost:8080/v2/api-docs , and converted it to YMAL at https://editor.swagger.io/ , which it could not show the example value/model as well. This seems to caused by the schema is not referring to the model object ("Car" here) correctly.
But from the API documentation of Swagger (https://docs.swagger.io/swagger-core/v1.5.0/apidocs/io/swagger/annotations/ApiResponse.html#response()), it says that the "response" attribute of the annotation @ApiResponse should correspond to the "schema" field of the specification.
By specifying response = "Object.class", shouldn't the Swagger UI populate the example value/model accordingly?
Welcome for any advice, and please kindly correct if I have any misconfigurations/misconceptions, thank you very much.
@GetMapping(path = "/car")
@ApiOperation(value = "Get car by color.", response = Car.class)
@ApiParam(value = "Color of the car.", required = true)
@ApiResponses(value = { @ApiResponse(code = 200, message = "OK.", response = Car.class),
@ApiResponse(code = 400, message = "Invalid color provided."),
@ApiResponse(code = 404, message = "Car not found.") })
public ResponseEntity<Object> getCarByColor(@RequestParam String color) {
return ResponseEntity.ok(testService.getCarByColor(color));
}
Model:
package com.example.demo.model;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@ApiModel(value = "Car", description = "The model for car")
@Data
public class Car {
@ApiModelProperty(notes = "Car ID.", example = "12345", required = false, position = 0)
private Long id;
@ApiModelProperty(notes = "Car name.", example = "Suzuki Swift 2020", required = true, position = 1)
@NotNull
@Max(value = 30, message = "Name can only have a maximum length of 30")
private String name;
@ApiModelProperty(notes = "Car color.", example = "blue", required = true, position = 2)
@NotNull
@Max(value = 30, message = "Color can only have a maximum length of 30")
@Pattern(regexp = "^(blue|yellow)$", message = "Only blue or yellow color is allowed.")
private String color;
public Car(Long id, String name, String color) {
this.id = id;
this.name = name;
this.color = color;
}
}
Swagger UI:
Springfox dependency in pom.xml:
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<UPDATE (31 Jul 2020)>
Made the following changes to use OAS3.0 specification and annotations, but still have issue. It also gives an error in Swagger UI.
REST controller and the annotations:
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
...
......
@GetMapping(path = "/car", produces = "application/json")
@Operation(summary = "Get car by color.", responses = {
@ApiResponse(responseCode = "200", description = "OK.", content = {
@Content(mediaType = "application/json", schema = @Schema(type = "object", implementation = Car.class)) }) })
public ResponseEntity<Object> getCarByColor(@RequestParam String color) {
return ResponseEntity.ok(testService.getCarByColor(color));
}
Model:
package com.example.demo.model;
import javax.validation.constraints.Max;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@ApiModel(value = "Car", description = "The model for car")
@Schema
@Data
public class Car {
@ApiModelProperty(notes = "Car ID.", example = "12345", required = false, position = 0)
private Long id;
@ApiModelProperty(notes = "Car name.", example = "Suzuki Swift 2020", required = true, position = 1)
@NotNull
@Max(value = 30, message = "Name can only have a maximum length of 30")
private String name;
@ApiModelProperty(notes = "Car color.", example = "blue", required = true, position = 2)
@NotNull
@Max(value = 30, message = "Color can only have a maximum length of 30")
@Pattern(regexp = "^(blue|yellow)$", message = "Only blue or yellow color is allowed.")
private String color;
public Car(Long id, String name, String color) {
this.id = id;
this.name = name;
this.color = color;
}
}
Swagger UI:
Upvotes: 5
Views: 20134
Reputation: 11
It seems that Swagger only exposes the models that we expose in the controller layer.To expose our internal models/DTOs, we need to configure additional models in the Docket bean in order to expose them.
@Bean
public Docket docket() {
return new Docket(DocumentationType.OAS_30)
.apiInfo(apiInfo())
.additionalModels(typeResolver.resolve(Car.class)) //configure your models/DTOs here
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
where the typeResolver
is an instance of com.fasterxml.classmate.TypeResolver
class which can be autowired
in your configuration class provided if you have included the dependency in your project.
Upvotes: 1
Reputation: 1
Using swagger-2 annotation worked for me by adding produces='application/json'
to @GetMapping
or any @RequestMapping
.
Upvotes: 0
Reputation: 81
In the case of using the springdoc-openapi-ui
(>=1.5.0) here is my working sample to show example data in the request and response sections of SwaggerUI if it's the JSON object.
Hopefully, it would fit your case with small changes too.
@Operation(summary = "Send some JSON")
@ApiResponses(value = {
@ApiResponse(
responseCode = "200",
description = "Success: our action has been completed",
content = @Content(mediaType = "application/json",
schema = @Schema(
type = "SampleHttpResponseDto",
example = "{\"status\":\"OK\",\"message\":\"sample OK answer\"}")))})
@PostMapping(value = "/resource", consumes = MediaType.APPLICATION_JSON_VALUE)
public SampleHttpResponseDto postRequest(
@Parameter(
name ="json",
schema = @Schema(
description = "additional description of the model",
type = "string",
example = "{\"status\":\"OK\",\"message\":\"message body\"}"))
@RequestBody Map<String, Object> request
) {
return new SampleHttpResponseDto(request.propert1, request.propert2);
}
Gist: https://gist.github.com/antukhov/7dece86c6d16cc81bb6f83f47ffc0c8d
SwaggerUI will look like this
Upvotes: 2
Reputation: 2744
You can override V3
models with V2
models. Just add a property in your application.properties
and your @ApiResponse
annotation should work properly.
springfox.documentation.swagger.use-model-v3=false
Make sure to use older @ApiResponses
and @ApiResponse
annotations.
This issue has been documented an https://github.com/springfox/springfox/issues/3503
Upvotes: 3