Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

swagger @ApiParam ignores certain properties

I have a Spring Boot Project with springfox-swagger2 2.7.0 And I have the following controller:

@Api(tags = { "Some" }, description = "CRUD for Some Stuff")
@RestController
@RequestMapping(path = "/some")
public class SomeController {

  @ApiOperation(value = "Get some")
  @GetMapping(value = "{someId}", produces = MediaType.APPLICATION_JSON_VALUE)
  public Response getSomeById(@PathVariable("someId") Id someId) {
    return ...;
  }
...
}

I want to control what is displayed in the docs by annotating the Id class, and this is working only for some parts of the annotation, but not all. The Id class (which has a registered converter from String to Id):

public class Id {

  @ApiParam(value = "This is the description", defaultValue = "1f1f1f",required = true, name = "someId", type = "string")
  private final Long id;

  public Id(Long id) {
    this.id = id;
  }

  public Long getId() {
    return id;
  }
}

Now the Swagger JSON returned looks as follows:

"parameters":[{
  "name":"id",
  "in":"query",
  "description":"This is the description",
  "required":true,
  "type":"integer",
  "default":"1f1f1f",
  "format":"int64"
}]

My question (or possibly bug report) is: why are some parts of the @ApiParam annotation used (like value, defaultValue and required), but others aren't, like name and type? Why does it seem like I cannot change the name or type here? For my particular use case, the latter is the one I would want to change to string.

Update

I've settled on adding the following component with the help from skadya.

@Component
public class OverrideSwaggerApiParamBuilder implements 
ExpandedParameterBuilderPlugin {

  @Override
  public boolean supports(DocumentationType type) {
    return DocumentationType.SWAGGER_2 == type;
  }

  @Override
  public void apply(ParameterExpansionContext context) {
    Optional<ApiParam> apiParamOptional = findApiParamAnnotation(context.getField().getRawMember());
    if (apiParamOptional.isPresent()) {
      ApiParam param = apiParamOptional.get();
      context.getParameterBuilder()
          .name(param.name())
          .modelRef(new ModelRef(param.type()))
          .build();
    }
  }
}

The Authors of springfox feel this could be a bug: https://github.com/springfox/springfox/issues/2107

like image 355
Michiel Haisma Avatar asked Nov 15 '17 21:11

Michiel Haisma


People also ask

How do I hide parameters in Swagger?

6. Using @ApiParam. @ApiParam is also a Swagger annotation that we can use to specify metadata related to request parameters. We can set the hidden property to true in order to hide any property.

What is @ApiParam in spring boot?

The @ApiParam annotation helps to specify the name, type, description (value), and example value of the parameter. Moreover, we can specify whether the parameter is required or optional.

What is SpringFox Swagger2?

Swagger2 is an open source project used to generate the REST API documents for RESTful web services. It provides a user interface to access our RESTful web services via the web browser. To enable the Swagger2 in Spring Boot application, you need to add the following dependencies in our build configurations file.

What is the annotation required to enable the Swagger?

Enable Swagger Swagger is enabled through the @EnableSwagger2 annotation. But this is not recommended. It is better to have a separate config class to enable and configure Swagger in your project. So, create a new class, SwaggerConfig.


1 Answers

By default, @ApiParam attribute 'name' and 'type' are used to override the parameter name and detected type of direct parameters specified in the API method. When you use @ApiParam on an field, the type and name are deduced by the field's name and its declared type and overriden value for name and type are not considered. (It looks by design in springfox, you may have a look at implementation springfox.documentation.swagger.readers.parameter.SwaggerExpandedParameterBuilder)

If you still wish to alter this behavior, you may register an custom implementation of springfox.documentation.spi.service.ExpandedParameterBuilderPlugin interlace.

For e.g.

@Component
public class OverrideSwaggerApiParamNameBuilder implements ExpandedParameterBuilderPlugin {

    @Override
    public boolean supports(DocumentationType type) {
        return DocumentationType.SWAGGER_2 == type;
    }

    @Override
    public void apply(ParameterExpansionContext context) {
        Optional<ApiParam> apiParamOptional = findApiParamAnnotation(context.getField().getRawMember());
        if (apiParamOptional.isPresent()) {
            fromApiParam(context, apiParamOptional.get());
        }
    }

    private void fromApiParam(ParameterExpansionContext context, ApiParam apiParam) {
        context.getParameterBuilder()
                .name(emptyToNull(apiParam.name()));
    }

    private String emptyToNull(String str) {
        return StringUtils.hasText(str) ? str : null;
    }
}

Hope it helps.

like image 85
skadya Avatar answered Sep 17 '22 15:09

skadya