restTemplate.getForEntity при чтении данных, содержащих список с одним элементом, дает исключение - PullRequest
1 голос
/ 13 марта 2019

У меня есть объект Detail, который имеет свойство объекта типа Product. Продукт имеет свойство с именем xxx, которое является массивом. Я делаю GET на URL с почтальоном, и результат выглядит так:

"Product": {
    "id": "2",
    "xxx": [
        "price": "50"
      },
      {
        "price": "60"
      }
    ]
  }

Этот результат хорош. Но в моем проекте Spring, когда я получаю Использование RestTemplate как:

  restTemplate.getForEntity("someurl", Detail.class).getBody();

Я получаю правильные результаты, когда список ххх содержит 2 или более элемента. Однако, когда в этом списке есть только элемент, я получаю сообщение об ошибке:

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token

  How do I fix this issue that I am facing with my call to restTemplate.getForEntity as above?

1 Ответ

0 голосов
/ 14 марта 2019

Я подозреваю, что вы сталкиваетесь с этой ошибкой не тогда, когда ваш список содержит один элемент, а когда у вас вообще нет списка, кроме простого объекта, таким образом, анализатор жалуется на неуместный START_OBJECT токен.Чтобы исправить это и не имея возможности редактировать сгенерированные Swagger классы домена, вы можете установить функцию десериализации

ObjectMapper objectMapper = new ObjectMapper(); // maybe injected
objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);

непосредственно на ObjectMapper, который вы используете.

Этот объект сопоставлениятеперь можно поместить в конфигурацию RestTemplate:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class JsonControllerIT {
    @LocalServerPort
    private int port;

    @Test
    public void jsonWithSerializationFeatureSet() {
        // given
        RestTemplate restTemplate = new RestTemplate();
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
        messageConverter.setObjectMapper(objectMapper);
        restTemplate.getMessageConverters().removeIf(m -> m.getClass().getName().equals(MappingJackson2HttpMessageConverter.class.getName()));
        restTemplate.getMessageConverters().add(messageConverter);

        // when
        Detail detail = restTemplate.getForEntity("http://localhost:" + port + "/json", Detail.class).getBody();

        // then
        assertThat(detail.getSingleItemList().get(0)).isEqualTo(3);
    }
}

Если вы используете подход Spring, имейте в виду, что вы также можете вводить все эти bean-компоненты, они созданы здесь просто, просто покажите их лучшевместе.

Вы также можете проверить этот текущий пример:

...