Swagger-ui为List <MonetartyAmount>显示为null

sma*_*kov 5 swagger swagger-ui springfox

我在springboot项目上使用swagger.端点出现问题,返回带有MonetaryAmount列表的实体ie(List<MonetaryAmount> rates)

Swagger-ui显示这些端点的错误数据:

{
  "rates": [
    null
  ]
}
Run Code Online (Sandbox Code Playgroud)

但是我希望将每个MonetaryAmount值看作Double和String对.像这样的Smth:

{
  "rates": [
   {"currency":"EUR", "rate": 12.23}
  ]
}
Run Code Online (Sandbox Code Playgroud)

我试图使用directModelSubstitute,但似乎它不适用于List.

这是我的模型:

public class CurrencyRatesResponse implements Serializable {

private List<MonetaryAmount> rates;

public CurrencyRatesResponse() {
}

public CurrencyRatesResponse(List<MonetaryAmount> rates) {
    this.rates = rates;
}

public List<MonetaryAmount> getRates() {
    return rates;
}

public void setRates(List<MonetaryAmount> rates) {
    this.rates = rates;
}
}
Run Code Online (Sandbox Code Playgroud)

这是我的端点的一个例子

@RequestMapping(path = "/public/rates", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public CurrencyRatesResponse getRates() {...}
Run Code Online (Sandbox Code Playgroud)

生成的招摇JSON:

 "/public/rates":{
         "get":{
            "tags":[
               "rate-endpoint"
            ],
            "summary":"getRates",
            "operationId":"getRatesUsingGET",
            "produces":[
               "application/json;charset=UTF-8"
            ],
            "parameters":[
               {
                 ....
               }
            ],
            "responses":{
               "200":{
                  "description":"OK",
                  "schema":{
                     "$ref":"#/definitions/CurrencyRatesResponse"
                  }
               },
               "401":{
                  "description":"Unauthorized"
               },
               "403":{
                  "description":"Forbidden"
               },
               "404":{
                  "description":"Not Found"
               }
            }
         }
      }
    }  ....

   "CurrencyRatesResponse":{
         "type":"object",
         "properties":{
            "rates":{
               "type":"array",
               "items":{
                  "$ref":"#/definitions/MonetaryAmount"
               }
            }
         },
         "title":"CurrencyRatesResponse"
      },
Run Code Online (Sandbox Code Playgroud)

Ami*_*iko 5

有几个步骤可以实现此目的。

首先,我们需要适当的objectMapper所以MonetaryAmount被映射到正确的对象有两个字段currencyrate。为此,我们需要为springfox的objectMapper添加自定义模块。

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;
import org.zalando.jackson.datatype.money.MoneyModule;
import springfox.documentation.schema.configuration.ObjectMapperConfigured;

@Component
public class SwaggerJacksonModule implements ApplicationListener<ObjectMapperConfigured> {

    @Override
    public void onApplicationEvent(ObjectMapperConfigured event) {
        event.getObjectMapper().registerModule(new MoneyModule());
    }
}
Run Code Online (Sandbox Code Playgroud)

说明: 我们向springfox的ObjectMapperConfigured事件添加了一个侦听器,并且每当触发该事件时,我们只需获取映射器并注册我们的模块。我使用Zalando的 Jackson数据类型货币库,所以我不写自己的库。

下一步将是实际的Swagger表示形式。让我们创建自己的表示形式对象MonetaryWrapper,用它来替代MonetaryAmount

public class MonetaryWrapper {

    private BigDecimal amount;

    private String currency;

  // getters and setters  (getters are important)
}
Run Code Online (Sandbox Code Playgroud)

为了正确获得单个对象表示,只需.directModelSubstitute(MonetaryAmount.class, MonetaryWrapper.class)将其添加到Docket对象即可。

但是,收集并不是那么简单。例如,在这种情况下列出。我们需要AlternateTypeRuleDocket对象中添加特殊对象,以使列表正确显示。

在springfox的文档中有关此主题的更多详细信息

像这样:

TypeResolver resolver = new TypeResolver();
AlternateTypeRule monetaryAmountListRule =
        newRule(resolver.resolve(List.class,  MonetaryAmount.class),
                resolver.resolve(List.class, MonetaryWrapper.class))
Run Code Online (Sandbox Code Playgroud)

最后,我们的Docketbean看起来像这样:

@Bean
public Docket productApi() {
    TypeResolver resolver = new TypeResolver();
    AlternateTypeRule monetaryAmountListRule =
            newRule(resolver.resolve(List.class,  MonetaryAmount.class),
                    resolver.resolve(List.class, MonetaryWrapper.class));


    return new Docket(DocumentationType.SWAGGER_2)
            .alternateTypeRules(monetaryAmountListRule)
            .directModelSubstitute(MonetaryAmount.class, MonetaryWrapper.class)
            .select().apis(RequestHandlerSelectors.basePackage("com.swagger.test"))
            .paths(PathSelectors.regex("/public.*")).build();
}
Run Code Online (Sandbox Code Playgroud)

还有一些演示屏幕截图:

执行请求时的演示:

DEMO端点结果

演示仅用于对象描述

演示代表结果