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

Issue with parsing the content from JSON file with Jackson & message- JsonMappingException -Cannot deserialize as out of START_ARRAY token

提问人:JJD 提问时间:10/12/2013 最后编辑:SyscallJJD 更新时间:11/22/2023 访问量:516604

问:

给定以下.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:无法在 [来源:android.content.res.AssetManager$AssetInputStream@416a5850;第 5 行,第 25 列]处从START_ARRAY令牌中反序列化 com.example.GeoPoint 的
实例
(通过引用链:com.example.Location[“center”])

Java 数组 JSON Jackson

评论

0赞 Smogger 10/12/2013
如果你可以简单地用 JSON 解析器解析它,你为什么要使用 Jackson
5赞 Katona 10/12/2013
您的 JSON 字符串格式不正确,类型是无效对象的数组。尝试在 JSON 字符串中替换 and with 和 with,这样它们就会成为对象。center[]{}longitudelatitude
1赞 JJD 10/16/2013
@Katona 谢谢。你能把你的评论变成答案,这样我就可以结束这个问题了吗?!
0赞 codester 9/29/2020
我遇到了同样的错误,但因为我使用了 LocalDate 类。一旦我用“mapper.registerModule(new JavaTimeModule());”添加了缺少的JavaTimeModule,问题就消失了。

答:

98赞 Katona 10/17/2013 #1

JSON 字符串格式错误:类型是无效对象的数组。将 and 替换为 和 和 在 JSON 字符串中,因此它们将成为对象:center[]{}longitudelatitude

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

评论

2赞 brebDev 3/13/2019
我遇到了同样的问题,但它很疯狂,因为在杰克逊 2.6.3v 中有一个完全不同的疯狂错误,而使用 2.9.8v 一切正常。该死的,所以这些序列化错误太烦人了。
0赞 Kanthishere 9/28/2020
阿图尔·夏尔马(Atul Sharma)回答 下面看起来与这个问题更相关。请审查和修改。谢谢
187赞 Abhijeet 11/4/2015 #2

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

这可以通过在参数中替换 来解决。 引用:ObjectObject[]geForObject("url",Object[].class)

  1. 参考文献1
  2. 参考文献2
  3. 参考文献3

评论

1赞 Beezer 4/28/2022
对于 Kotliners,下面是一个示例: val result: ResponseEntity<Array<BillingType>> = restTemplate.getForEntity(uri, Array<BillingType>::class.java)
16赞 freedev 2/2/2018 #3

如前所述,Jackson 对象映射器会抛出异常,因为它期望一个,而它找到了一个响应。JsonMappingException: out of START_ARRAY tokenObject {}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;
}

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

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

评论

1赞 JJD 2/6/2018
感谢您分享此替代实现。你能说出使用与使用有什么优点或缺点吗?CollectionTypeTypeReference
1赞 freedev 2/7/2018
TypeReference语法比其他语法短得多。不确定,在某些情况下是否可能存在与类型擦除相关的反指示......但在我的世界里,它只是更容易使用和理解。TypeReference
20赞 Atul KS 12/27/2018 #4

我将这个问题分类为从 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");
}

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

结果:

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

评论

1赞 Aaria 5/17/2020
这解决了我几天来一直遇到的问题,没有其他答案有意义。对于有相同错误的其他任何人。值得注意的是,如果你的 JSON 中有多个对象,则需要返回多个对象。我一直在返回 MyObject,我应该返回 MyObject[]
-1赞 27P 4/14/2022 #5

例如:

数据类

data class ToDo(
var id: Int, 
var text: String?, 
var completed: Boolean?) {}

使用 ToDo::class.java 但不对 json 列表使用 Array::class.java 时引发上述反序列化错误

不起作用

    private val mapper = ObjectMapper().registerKotlinModule()
    .....
    val todo= mapper.readValue(response.body(), ToDo::class.java)

com.fasterxml.jackson.databind.exc.MismatchedInputException:无法 从 Array 值反序列化类型的值 (token ) at [来源: (String)“[{”id“:14,”text“:”TEST“,”completed“:true},{”id“:13,”text“:”TEST“,”completed“:true},{”id“:19,”text“:”TEST“,”completed“:true”[截断 84 个字符];行:1,列:1]com.example.api.dto.ToDoJsonToken.START_ARRAY

工作

private val mapper = ObjectMapper().registerKotlinModule()
.....
val todos = mapper.readValue(response.body(), Array<ToDo>::class.java)
0赞 martosfre 11/22/2023 #6

如果您使用的是 Web 服务,则问题可能出在正文值上。您可以通过以下方式使用数组发送值

enter image description here

并获取错误

enter image description here

要修复它,您必须将正文正确更改为对象

enter image description here

问候