提问人:JJD 提问时间:10/12/2013 最后编辑:SyscallJJD 更新时间:11/22/2023 访问量:516604
使用 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
问:
给定以下.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”])
答:
JSON 字符串格式错误:类型是无效对象的数组。将 and 替换为 和 和 在 JSON 字符串中,因此它们将成为对象:center
[
]
{
}
longitude
latitude
[
{
"name" : "New York",
"number" : "732921",
"center" : {
"latitude" : 38.895111,
"longitude" : -77.036667
}
},
{
"name" : "San Francisco",
"number" : "298732",
"center" : {
"latitude" : 37.783333,
"longitude" : -122.416667
}
}
]
评论
JsonMappingException: out of START_ARRAY token
异常是由 Jackson 对象映射器抛出的,因为它期待一个,而它找到了一个响应。Object {}
Array [{}]
这可以通过在参数中替换 来解决。
引用:Object
Object[]
geForObject("url",Object[].class)
评论
如前所述,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;
}
另一方面,如果你没有像这样的 pojo,你可以使用:Location
TypeReference<List<Map<String, Object>>> typeReference = new TypeReference<>() {};
return objectMapper.readValue(inputStream, typeReference);
评论
CollectionType
TypeReference
TypeReference
语法比其他语法短得多。不确定,在某些情况下是否可能存在与类型擦除相关的反指示......但在我的世界里,它只是更容易使用和理解。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");
}
注意:是具有 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
评论
例如:
数据类
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.ToDo
JsonToken.START_ARRAY
工作
private val mapper = ObjectMapper().registerKotlinModule()
.....
val todos = mapper.readValue(response.body(), Array<ToDo>::class.java)
如果您使用的是 Web 服务,则问题可能出在正文值上。您可以通过以下方式使用数组发送值
并获取错误
要修复它,您必须将正文正确更改为对象
问候
评论
center
[
]
{
}
longitude
latitude