使用 Jackson 和消息解析 JSON 文件中的内容时出现问题 - JsonMappingException - 无法反序列化为超出 START_ARRAY 令牌

Posted

技术标签:

【中文标题】使用 Jackson 和消息解析 JSON 文件中的内容时出现问题 - JsonMappingException - 无法反序列化为超出 START_ARRAY 令牌【英文标题】:Issue with parsing the content from JSON file with Jackson & message- JsonMappingException -Cannot deserialize as out of START_ARRAY token 【发布时间】:2013-10-20 10:00:48 【问题描述】:

给定以下 .json 文件:

[
    
        "name" : "New York",
        "number" : "732921",
        "center" : [
                "latitude" : 38.895111, 
                "longitude" : -77.036667
            ]
    ,
    
        "name" : "San Francisco",
        "number" : "298732",
        "center" : [
                "latitude" : 37.783333, 
                "longitude" : -122.416667
            ]
    
]

我准备了两个类来表示包含的数据:

public class Location 
    public String name;
    public int number;
    public GeoPoint center;

...

public class GeoPoint 
    public double latitude;
    public double longitude;

为了解析 .json 文件中的内容,我使用了Jackson 2.2.x 并准备了以下方法:

public static List<Location> getLocations(InputStream inputStream) 
    ObjectMapper objectMapper = new ObjectMapper();
    try 
        TypeFactory typeFactory = objectMapper.getTypeFactory();
        CollectionType collectionType = typeFactory.constructCollectionType(
                                            List.class, Location.class);
        return objectMapper.readValue(inputStream, collectionType);
     catch (IOException e) 
        e.printStackTrace();
    
    return null;

只要我省略了center 属性,所有内容都可以被解析。但是,当我尝试解析地理坐标时,我最终会收到以下错误消息:

com.fasterxml.jackson.databind.JsonMappingException:无法反序列化的实例 com.example.GeoPoint 在 [Source: android.content.res.AssetManager$AssetInputStream@416a5850;行:5,列:25] (通过引用链:com.example.Location["center"])

【问题讨论】:

如果可以简单地用json解析器解析,为什么还要使用jackson 您的 JSON 字符串格式错误,center 的类型是无效对象数组。尝试将 longitudelatitude 周围 JSON 字符串中的 替换为 [],这样它们就会成为对象。 @Katona 谢谢。您能否将您的评论转换为答案,以便我关闭问题?! 我遇到了同样的错误,但因为我使用了 LocalDate 类。一旦我用“mapper.registerModule(new JavaTimeModule());”添加了缺失的 JavaTimeModule ,问题就解决了。 【参考方案1】:

JsonMappingException: out of START_ARRAY token 异常由 Jackson 对象映射器抛出,因为它期待 Object ,而它找到了 Array [] 作为响应。

这可以通过在geForObject("url",Object[].class) 的参数中将Object 替换为Object[] 来解决。 参考资料:

    Ref.1 Ref.2 Ref.3

【讨论】:

【参考方案2】:

您的 JSON 字符串格式错误:center 的类型是无效对象数组。将longitudelatitude 周围的JSON 字符串中的[] 替换为,这样它们就会成为对象:

[
    
        "name" : "New York",
        "number" : "732921",
        "center" : 
                "latitude" : 38.895111, 
                "longitude" : -77.036667
            
    ,
    
        "name" : "San Francisco",
        "number" : "298732",
        "center" : 
                "latitude" : 37.783333, 
                "longitude" : -122.416667
            
    
]

【讨论】:

我遇到了同样的问题,但它很疯狂,因为在 jackson 2.6.3v 中有一个完全不同的疯狂错误,并且在 2.9.8v 中一切正常。该死,所以这些序列化错误太烦人了。 Atul Sharma answer 下面看起来与这个问题更相关。请检查和修改。谢谢【参考方案3】:

我将此问题分类为验证来自 JSONLint.com 的 json,然后更正它。这是相同的代码。

String jsonStr = "[\r\n" + "\"name\":\"New York\",\r\n" + "\"number\": \"732921\",\r\n"+ "\"center\": \r\n" + "\"latitude\": 38.895111,\r\n"  + " \"longitude\": -77.036667\r\n" + "\r\n" + ",\r\n" + " \r\n"+ "\"name\": \"San Francisco\",\r\n" +\"number\":\"298732\",\r\n"+ "\"center\": \r\n" + "    \"latitude\": 37.783333,\r\n"+ "\"longitude\": -122.416667\r\n" + "\r\n" + "\r\n" + "]";

ObjectMapper mapper = new ObjectMapper();
MyPojo[] jsonObj = mapper.readValue(jsonStr, MyPojo[].class);

for (MyPojo itr : jsonObj) 
    System.out.println("Val of name is: " + itr.getName());
    System.out.println("Val of number is: " + itr.getNumber());
    System.out.println("Val of latitude is: " + 
        itr.getCenter().getLatitude());
    System.out.println("Val of longitude is: " + 
        itr.getCenter().getLongitude() + "\n");

注意:MyPojo[].class 是具有 json 属性的 getter 和 setter 的类。

结果:

Val of name is: New York
Val of number is: 732921
Val of latitude is: 38.895111
Val of longitude is: -77.036667
Val of name is: San Francisco
Val of number is: 298732
Val of latitude is: 37.783333
Val of longitude is: -122.416667

【讨论】:

这解决了我几天来一直遇到的问题,没有其他答案有意义。对于其他有同样错误的人。值得注意的是,如果您的 JSON 中有多个对象,则需要返回多个对象。我一直在返回 MyObject,我应该返回 MyObject[]【参考方案4】:

如前所述,Jackson 对象映射器抛出 JsonMappingException: out of START_ARRAY token 异常,因为它期待 Object ,而它发现 Array [] 作为响应。

更简单的解决方案可能是将方法 getLocations 替换为:

public static List<Location> getLocations(InputStream inputStream) 
    ObjectMapper objectMapper = new ObjectMapper();
    try 
        TypeReference<List<Location>> typeReference = new TypeReference<>() ;
        return objectMapper.readValue(inputStream, typeReference);
     catch (IOException e) 
        e.printStackTrace();
    
    return null;

另一方面,如果你没有像 Location 这样的 pojo,你可以使用:

TypeReference<List<Map<String, Object>>> typeReference = new TypeReference<>() ;
return objectMapper.readValue(inputStream, typeReference);

【讨论】:

感谢您分享这个替代实现。您能说出使用CollectionTypeTypeReference 的优缺点吗? TypeReference 语法比其他语法短得多。不确定,如果在某些情况下可能有与类型擦除相关的反指示......但在我的世界里,TypeReference 更容易使用和理解。

以上是关于使用 Jackson 和消息解析 JSON 文件中的内容时出现问题 - JsonMappingException - 无法反序列化为超出 START_ARRAY 令牌的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Jackson 和 MongoDB 传递 JSON 消息中的属性?

jackson 解析json ,使用注解

java使用jackson生成和解析JSON

Java下利用Jackson进行JSON解析和序列化

Java下利用Jackson进行JSON解析和序列化1

Java下利用Jackson进行JSON解析和序列化