简体   繁体   English

读取包含包含单个元素的列表的数据时,restTemplate.getForEntity给出异常

[英]restTemplate.getForEntity when reading data that contains a list with single element gives Exception

I have a Detail object that has a property of object of type Product. 我有一个Detail对象,该对象具有Product类型的对象的属性。 Product has a property called xxx which is an arraylist. 产品具有名为xxx的属性,该属性是一个数组列表。 I do a GET on the URL with postman and the result looks like: 我用邮递员在URL上执行GET,结果如下所示:

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

This result is good. 这个结果很好。 But, in my Spring project, when I do a get Using RestTemplate as: 但是,在我的Spring项目中,当我执行使用RestTemplate作为:

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

I get correct results when xxx list contains 2 or more element. 当xxx列表包含2个或更多元素时,我得到正确的结果。 However, when there is only element in this list, I get an error: 但是,当此列表中只有元素时,出现错误:

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?

I suspect that your encounter this error not when your list contains one item but rather when you have no list at all but a plain object, thus the parser complains about a misplaced START_OBJECT token. 我怀疑您不是在列表包含一个项目时遇到此错误,而是在您没有列表但只有一个普通对象的情况下遇到此错误,因此解析器抱怨START_OBJECT了一个错误的START_OBJECT令牌。 To remedy this and without being able to edit Swagger-generated domain classes, you could set the deserialization feature 为了解决此问题,并且无法编辑Swagger生成的域类,可以设置反序列化功能

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

directly on the ObjectMapper that you are using. 直接在您使用的ObjectMapper上。

This object mapper can now be put into the RestTemplate config: 现在可以将该对象映射器放入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);
    }
}

If you use the Spring-approach keep in mind that you also can inject all those beans, they are created here straight-forward just show them better together. 如果您使用Spring方法,请记住您也可以注入所有这些bean,它们在此处直接创建的只是将它们更好地展示在一起。

You can also check this running example: 您还可以检查以下运行示例:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM