swagger @ApiParam忽略了某些属性

时间:2017-11-15 21:29:11

标签: java spring-boot swagger swagger-ui swagger-2.0

我有springfox-swagger2 2.7.0的Spring Boot项目我有以下控制器:

@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 ...;
  }
...
}

我想通过注释Id类来控制文档中显示的内容,这仅适用于注释的某些部分,但不是全部。 Id类(已注册转换器从StringId):

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;
  }
}

现在返回的Swagger JSON看起来如下:

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

我的问题(或可能是错误报告)是:为什么使用@ApiParam注释的某些部分(例如valuedefaultValuerequired),但其他部分不是&{ #39; t,如nametype? 为什么我似乎无法在此处更改nametype? 对于我的特定用例,后者是我想要更改为string的那个。

更新

我已经决定在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();
    }
  }
}

springfox的作​​者认为这可能是一个错误:https://github.com/springfox/springfox/issues/2107

4 个答案:

答案 0 :(得分:6)

默认情况下,@ ApacheParam属性'name'和'type'用于覆盖API方法中指定的参数名称和检测到的直接参数类型。在字段上使用@ApiParam时,类型和名称由字段名称推断,其声明的类型和名称和类型的覆盖值不予考虑。 (它看起来像是在springfox中的设计,你可能会看一下实现springfox.documentation.swagger.readers.parameter.SwaggerExpandedParameterBuilder

如果您仍希望更改此行为,则可以注册springfox.documentation.spi.service.ExpandedParameterBuilderPlugin隔行扫描的自定义实现。

例如

@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;
    }
}

希望它有所帮助。

答案 1 :(得分:0)

实际上可以编译并考虑ApiParam类型属性或Model dataType属性中类型设置的更完整解决方案:

@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1000)
public class OverrideSwaggerApiParamTypeBuilder extends 
SwaggerExpandedParameterBuilder implements ExpandedParameterBuilderPlugin {

public OverrideSwaggerApiParamTypeBuilder(DescriptionResolver descriptions, EnumTypeDeterminer enumTypeDeterminer) {
    super(descriptions, enumTypeDeterminer);
}

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

public void apply(ParameterExpansionContext context) {
    super.apply(context);
    Optional<ApiModelProperty> apiModelPropertyOptional = context.findAnnotation(ApiModelProperty.class);
    if (apiModelPropertyOptional.isPresent()) {
        if(!StringUtils.isAllEmpty(apiModelPropertyOptional.get().dataType())) {
            context.getParameterBuilder().modelRef(new ModelRef(apiModelPropertyOptional.get().dataType()));
        }
    }

    Optional<ApiParam> apiParamOptional = context.findAnnotation(ApiParam.class);
    if (apiParamOptional.isPresent()) {
        if(!StringUtils.isAllEmpty(apiParamOptional.get().type())) {
            context.getParameterBuilder().modelRef(new ModelRef(apiParamOptional.get().type()));
        }
    }

}

}

答案 2 :(得分:-1)

理想情况下,您需要将@ApiParam与方法参数一起使用,而@ApiModelProperty与模型属性一起使用。

public @interface ApiParam {
    /**
     * The parameter name.
     * The name of the parameter will be derived from the field/method/parameter name,
     * however you can override it.
     * Path parameters must always be named as the path section they represent.
     */
    String name() default "";

不确定是否存在type属性,但下面是处理类型的方法:

public @interface ApiModelProperty {

    /**
     * The data type of the parameter.
     * This can be the class name or a primitive. The value will override the data type as read from the class
     * property.
     */
    String dataType() default "";

......

答案 3 :(得分:-1)

我使用的是2.6.1版,无法在@ApiParam中找到“type”属性,而我可以看到你正在使用“type”。所以确保它可以使用。我还提到@ApiModelProperty提供了dataType()来处理你提到的场景。