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

给定以下.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属性,所有内容都可以被解析。但是,当我尝试解析地理坐标时,我得到以下错误消息:

异常: 无法反序列化
来源: android.content.res. AssetManager $AssetInputStream@416a5850; line: 5,column: 25]
(通过引用链: com.example. Location [“ center”])

459577 次浏览

您的 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 对象映射器抛出 JsonMappingException: out of START_ARRAY token异常,因为它期待一个 Object {},而它发现一个 Array [{}]作为响应。

这可以通过在 geForObject("url",Object[].class)的参数中用 Object[]代替 Object来解决。 参考文献:

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

如前所述,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);

我将这个问题归类为验证 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

例如:

资料类别

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

当您使用 ToDo: : class.java 而不是 Array: : class.java for json list 时抛出上面的反序列化错误

不起作用

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

异常: 不能 从 Array 值反序列化类型 com.example.api.dto.ToDo的值 (令牌 JsonToken.START_ARRAY)来源: (String)”[{“ id”: 14,“ text”: “ TEST”,“ complete”: true } ,{“ id”: 13,“ text”: “ TEST”,“ complete”: true } ,{“ id”: 19,“ text”: “ TEST”,“ complete”: true”[截断 行: 1,列: 1]

工作

private val mapper = ObjectMapper().registerKotlinModule()
.....
val todos = mapper.readValue(response.body(), Array<ToDo>::class.java)