jackson 无法在Spring Web服务中反序列化START_ARRAY标记外的对象示例

mm9b1k5b  于 2022-11-08  发布在  Spring
关注(0)|答案(4)|浏览(238)

我目前在android上连接Web服务时遇到问题。我使用jackson-core/databind/annotation-2.2.4和Spring RESTWebService。如果我从浏览器访问URL,我可以看到JSON响应:(服务器返回List\Shop\类似于:)

[{"name":"shopqwe","mobiles":[],"address":{"town":"city",
"street":"streetqwe","streetNumber":"59","cordX":2.229997,"cordY":1.002539},
"shoe" [{"shoeName":"addidas","number":"631744030","producent":"nike","price":999.0,
"sizes":[30.0,35.0,38.0]}]

从客户端端点(Android应用程序),我收到此错误消息:

08-26 17:43:07.406: E/AllShopsAsyc(28203): Could not read JSON: Can not deserialize
instance of com.auginzynier.data.ShopContainer out of START_ARRAY token
08-26 17:43:07.406: E/AllShopsAsyc(28203):  at [Source:
com.android.okhttp.internal.http.HttpTransport$ChunkedInputStream@41efbd48; line: 1,
column: 1]; nested exception is com.fasterxml.jackson.databind.JsonMappingException:
Can not deserialize instance of com.auginzynier.data.ShopContainer out of START_ARRAY
token
08-26 17:43:07.406: E/AllShopsAsyc(28203):  at [Source:
com.android.okhttp.internal.http.HttpTransport$ChunkedInputStream@41efbd48; line: 1,
column: 1] 
08-26 17:43:07.406: E/AllShopsAsyc(28203):
org.springframework.http.converter.HttpMessageNotReadableException: Could not read
JSON: Can not deserialize instance of com.auginzynier.data.ShopContainer out of
START_ARRAY token

我的服务器请求

RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
ShopContainer response  = restTemplate.getForObject(url, ShopContainer.class);

其中,ShopContainer为:

public class ShopContainer {
   private List<Shop> shops;

商店、地址和鞋的结构是:(我已经省略了getter和setter):

public class Shop {
@JsonProperty("name")    private String name;
@JsonProperty("mobiles")   private List<String> mobiles = new ArrayList<String>();
@JsonProperty("address")   private Address address;
@JsonProperty("shoe") private List<Shoe> shoe = new ArrayList<Shoe>();

public class Address {
@JsonProperty("town") private String town;
@JsonProperty("street") private String street;
@JsonProperty("streetNumber") private String streetNumber;
@JsonProperty("cordX") private Double cordX;
@JsonProperty("cordY") private Double cordY;

public class Shoe {
@JsonProperty("shoeName") private String shoeName;
@JsonProperty("number") private String number;
@JsonProperty("producent") private String producent;
@JsonProperty("price") private Double price;
@JsonProperty("sizes") private List<Double> sizes = new ArrayList<Double>();

我已经在这里和谷歌上看过了,但仍然不能弄清楚我在这一点上错过了什么。
任何回应都将是非常有帮助的。
祝你好运

@更新

我已经通过使用Jackson的ObjectMapper和RequestMethod. GET修复了JSON,它现在返回一个String。

list is List<Shop>

ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(new File("D:\\Android\\shop.json"), list);
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(list));
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(list);

控制台中的JSON如下所示:

[ {
  "name" : "shopqwe",
  "mobiles" : [ ],
  "address" : {
    "town" : "city",
    "street" : "streetqwe",
    "streetNumber" : "59",
    "cordX" : 2.229997,
    "cordY" : 2.002539
  },
  "shoe" : [ {
    "shoeName" : "addidas",
    "number" : "631744033",
    "producent" : "nike",
    "price" : 10.0,
    "sizes" : [ 30.0, 35.0, 38.0 ]
  } ]
} ]

请求仍然不起作用-错误是相同的。

wfveoks0

wfveoks01#

您的json包含一个数组,但您试图将其解析为一个对象。发生此错误的原因是对象必须以{开头。
您有两个选项:
1.您可以去掉ShopContainer类,改用Shop[]

ShopContainer response  = restTemplate.getForObject(
    url, ShopContainer.class);

替换为

Shop[] response  = restTemplate.getForObject(url, Shop[].class);

然后用它制作你想要的东西。
1.您可以更改服务器以返回对象而不是列表

return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(list);

替换为

return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(
    new ShopContainer(list));
yqkkidmi

yqkkidmi2#

如果想当然地认为您发布的JSON实际上就是您在浏览器中看到的内容,那么问题就出在JSON本身。
您发布的JSON代码段格式不正确。
您已发布:

[{
        "name" : "shopqwe",
        "mobiles" : [],
        "address" : {
            "town" : "city",
            "street" : "streetqwe",
            "streetNumber" : "59",
            "cordX" : 2.229997,
            "cordY" : 1.002539
        },
        "shoe"[{
                "shoeName" : "addidas",
                "number" : "631744030",
                "producent" : "nike",
                "price" : 999.0,
                "sizes" : [30.0, 35.0, 38.0]
            }]

而正确的JSON应该是:

[{
        "name" : "shopqwe",
        "mobiles" : [],
        "address" : {
            "town" : "city",
            "street" : "streetqwe",
            "streetNumber" : "59",
            "cordX" : 2.229997,
            "cordY" : 1.002539
        },
        "shoe" : [{
                "shoeName" : "addidas",
                "number" : "631744030",
                "producent" : "nike",
                "price" : 999.0,
                "sizes" : [30.0, 35.0, 38.0]
            }
        ]
    }
]
4szc88ey

4szc88ey3#

我在使用spring-boot-starter-data-redis时也遇到过类似的问题。在我的实现中,为RedisTemplate提供了一个@Bean,如下所示:

@Bean
public RedisTemplate<String, List<RoutePlantCache>> redisTemplate(RedisConnectionFactory connectionFactory) {
    final RedisTemplate<String, List<RoutePlantCache>> template = new RedisTemplate<>();
    template.setConnectionFactory(connectionFactory);
    template.setKeySerializer(new StringRedisSerializer());
    template.setValueSerializer(new Jackson2JsonRedisSerializer<>(RoutePlantCache.class));

    // Add some specific configuration here. Key serializers, etc.
    return template;
}

修复方法是指定RoutePlantCache数组,如下所示:

template.setValueSerializer(new Jackson2JsonRedisSerializer<>(RoutePlantCache[].class));

下面的例外我有:

com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `[...].RoutePlantCache` out of START_ARRAY token
 at [Source: (byte[])"[{ ... },{ ... [truncated 1478 bytes]; line: 1, column: 1]
    at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:59) ~[jackson-databind-2.11.4.jar:2.11.4]
    at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1468) ~[jackson-databind-2.11.4.jar:2.11.4]
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1242) ~[jackson-databind-2.11.4.jar:2.11.4]
    at com.fasterxml.jackson.databind.DeserializationContext.handleUnexpectedToken(DeserializationContext.java:1190) ~[jackson-databind-2.11.4.jar:2.11.4]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeFromArray(BeanDeserializer.java:604) ~[jackson-databind-2.11.4.jar:2.11.4]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:190) ~[jackson-databind-2.11.4.jar:2.11.4]
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:166) ~[jackson-databind-2.11.4.jar:2.11.4]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4526) ~[jackson-databind-2.11.4.jar:2.11.4]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3572) ~[jackson-databind-2.11.4.jar:2.11.4]
50few1ms

50few1ms4#

在我的例子中,我有一个不正确的返回类型。返回类型是UserPost,但它应该是List,这解决了前面提到的方法

Before

    fun getApiCallResponse(): UserPost {
        val userPosts = HttpClientHelper.getUserPostsUrl()
        val response = memberHttpHelper.get(userPosts)
        return jacksonUtils.fromJson(response, object : 
        TypeReference<ArrayList<UserPost>>() {})
    }

After

    fun getApiCallResponse(): List<UserPost> {
        val userPosts = HttpClientHelper.getUserPostsUrl()
        val response = memberHttpHelper.get(userPosts)
        return jacksonUtils.fromJson(response, object : 
        TypeReference<ArrayList<UserPost>>() {})
    }

相关问题