Swagger-ui 显示 List<MonetartyAmount> 为空
Swagger-ui shows null for List<MonetartyAmount>
我在我的 springboot 项目中使用 swagger。
问题出现在 returns 具有 MonetaryAmount 列表的实体的端点,即 (List<MonetaryAmount> rates
)
Swagger-ui 为以下端点显示不正确的数据:
{
"rates": [
null
]
}
但是我希望看到每个 MonetaryAmount 值都是 Double 和 String 对。像这样:
{
"rates": [
{"currency":"EUR", "rate": 12.23}
]
}
我尝试使用 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;
}
}
这是我的端点示例
@RequestMapping(path = "/public/rates", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public CurrencyRatesResponse getRates() {...}
生成的 swagger 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"
},
有几个步骤可以实现。
首先,我们需要适当的 objectMapper,以便 MonetaryAmount
映射到具有两个字段 currency
和 rate
的适当 object。为此,我们需要为 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());
}
}
解释: 我们向 springfox 的 ObjectMapperConfigured
事件添加一个侦听器,每当事件被触发时,我们只需获取映射器并注册我们的模块。我使用 Zalando's Jackson Datatype Money 库,这样我就不用自己写了。
下一步将处理实际的 Swagger 表示。让我们创建我们自己的表示 object MonetaryWrapper
我们将用它来替代 MonetaryAmount
.
public class MonetaryWrapper {
private BigDecimal amount;
private String currency;
// getters and setters (getters are important)
}
为了获得正确的单个 object 表示,将 .directModelSubstitute(MonetaryAmount.class, MonetaryWrapper.class)
添加到 Docket
object.
就足够了
但是 collections 没那么简单。例如在这种情况下列出。我们需要将 Special AlternateTypeRule
object 添加到 Docket
object 中,以便正确显示列表。
在 springfox 的 documentation
中有关于此主题的更多详细信息
像这样:
TypeResolver resolver = new TypeResolver();
AlternateTypeRule monetaryAmountListRule =
newRule(resolver.resolve(List.class, MonetaryAmount.class),
resolver.resolve(List.class, MonetaryWrapper.class))
最后我们的 Docket
bean 看起来像这样:
@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();
}
这里还有一些演示截图:
执行请求时的演示:
演示仅用于 object 描述:
我在我的 springboot 项目中使用 swagger。
问题出现在 returns 具有 MonetaryAmount 列表的实体的端点,即 (List<MonetaryAmount> rates
)
Swagger-ui 为以下端点显示不正确的数据:
{
"rates": [
null
]
}
但是我希望看到每个 MonetaryAmount 值都是 Double 和 String 对。像这样:
{
"rates": [
{"currency":"EUR", "rate": 12.23}
]
}
我尝试使用 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;
}
}
这是我的端点示例
@RequestMapping(path = "/public/rates", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public CurrencyRatesResponse getRates() {...}
生成的 swagger 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"
},
有几个步骤可以实现。
首先,我们需要适当的 objectMapper,以便 MonetaryAmount
映射到具有两个字段 currency
和 rate
的适当 object。为此,我们需要为 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());
}
}
解释: 我们向 springfox 的 ObjectMapperConfigured
事件添加一个侦听器,每当事件被触发时,我们只需获取映射器并注册我们的模块。我使用 Zalando's Jackson Datatype Money 库,这样我就不用自己写了。
下一步将处理实际的 Swagger 表示。让我们创建我们自己的表示 object MonetaryWrapper
我们将用它来替代 MonetaryAmount
.
public class MonetaryWrapper {
private BigDecimal amount;
private String currency;
// getters and setters (getters are important)
}
为了获得正确的单个 object 表示,将 .directModelSubstitute(MonetaryAmount.class, MonetaryWrapper.class)
添加到 Docket
object.
但是 collections 没那么简单。例如在这种情况下列出。我们需要将 Special AlternateTypeRule
object 添加到 Docket
object 中,以便正确显示列表。
在 springfox 的 documentation
中有关于此主题的更多详细信息像这样:
TypeResolver resolver = new TypeResolver();
AlternateTypeRule monetaryAmountListRule =
newRule(resolver.resolve(List.class, MonetaryAmount.class),
resolver.resolve(List.class, MonetaryWrapper.class))
最后我们的 Docket
bean 看起来像这样:
@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();
}
这里还有一些演示截图:
执行请求时的演示:
演示仅用于 object 描述: