Swagger-UI показывает ноль для списка <MonetartyAmount> - PullRequest
0 голосов
/ 01 мая 2018

Я использую Swagger в своем проекте Springboot. Проблема возникает для конечной точки, которая возвращает сущность со списком 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() {...}

Генерируемое чванство 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"
      },

1 Ответ

0 голосов
/ 08 июня 2018

Для этого есть несколько шагов.

Прежде всего, нам нужен правильный objectMapper, чтобы MonetaryAmount отображался на нужный объект с двумя полями currency и rate. Для этого нам нужно добавить пользовательский модуль для objectMapper в Springfox.

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

Объяснение: Мы добавляем слушателя к событию ObjectMapperConfigured в Springfox, и всякий раз, когда событие запускается, мы просто получаем преобразователь и регистрируем наш модуль. Я использую библиотеку данных типа Джексона Заландо, чтобы не писать свою собственную.

Следующим шагом будет работа над фактическим представлением Swagger. Давайте создадим наш собственный объект представления MonetaryWrapper, который мы будем использовать для замены MonetaryAmount.

public class MonetaryWrapper {

    private BigDecimal amount;

    private String currency;

  // getters and setters  (getters are important)
}

Для правильного представления одиночного объекта достаточно добавить .directModelSubstitute(MonetaryAmount.class, MonetaryWrapper.class) к Docket объекту.

НО Это не так просто для коллекций. например, список в этом случае. Нам нужно добавить объект Special AlternateTypeRule в объект Docket, чтобы списки отображались правильно.

Подробнее об этой теме в документации Springfox

Примерно так:

TypeResolver resolver = new TypeResolver();
AlternateTypeRule monetaryAmountListRule =
        newRule(resolver.resolve(List.class,  MonetaryAmount.class),
                resolver.resolve(List.class, MonetaryWrapper.class))

И, наконец, наш Docket боб будет выглядеть примерно так:

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

И некоторые демонстрационные скриншоты здесь:

Демонстрация при выполнении запроса:

DEMO endpoint result

Демо просто для описание объекта :

Demo representation result

...