我有这样的POJO
class POJO {
Map<Integer, Integer> map;
//Getter and Setter for map here
}
我有一个json(POJO列表)
[
{
"200": 10
},
{
"20": 100,
"30": 400
}
]
杰克逊反序列化期间如果我这样做
String s = ... //s has the above json
List<POJO> pojoList = mapper.readValue(s, new TypeReference<List<POJO>>() {});
System.out.println(pojoList.get(0).getMap().get(20)); //prints 100
然后没有问题
但如果我使用像
那样的通用列表List<POJO> pojoList = mapper.readValue(s, List.class);
然后在System.out.println
投掷ClassCastException
java.util.LinkedHashMap cannot be cast to mycode.model.POJO
据我所知,如果我告诉杰克逊List
,它会将每个对象反序列化为Map而不是类型POJO。因此,当我尝试访问pojoList.get(0).getMap()
时,它会抛出异常
(注意:打印pojoList.get(0)
没有问题,并打印{"200":10}
)
我的问题是为什么在反序列化过程中它不会抛出异常。 LHS上的对象类型是否被忽略了?
谢谢..
答案 0 :(得分:2)
我的问题是为什么在反序列化期间它没有抛出异常 本身。 LHS上的对象类型是否被忽略了?
您对Java的工作方式存在误解。这两个语句的运行时评估
List<POJO> pojoList = mapper.readValue(s, List.class);
mapper.readValue(s, List.class);
完全一样。换句话说,指定的变量在运行时不起作用。在编译时,它的所有优点都可能为泛型和poly expressions提供上下文。
当您调用
时mapper.readValue(s, List.class);
你告诉杰克逊将JSON反序列化为List
。而已。你没有给它任何其他信息。杰克逊绝对没有办法猜测你是指POJO
或其他任何东西的清单。因此,杰克逊猜测并使用自己的默认值。对于JSON对象,默认值为LinkedHashMap
。
此外,List.class
评估为Class<List>
,因此readValue
的返回类型为原始List
类型。使用原始类型时,将删除泛型。因此,您不会收到编译错误,但是您应该收到有关未选中转换的警告。
你应该阅读
另一方面,这个
List<POJO> pojoList = mapper.readValue(s, new TypeReference<List<POJO>>() {});
有效,因为您正在向Jackson所有正确反序列化JSON所需的信息。它是List
(JSON数组)的POJO
元素(JSON对象)。
readValue
的返回类型(即编译时间)是从上下文(我之前提到过)推断出来的,并绑定到List<POJO>
,因为这是您将结果赋给的表达式的类型。 TypeReference
在此处未提供泛型的类型信息。因此,您可以执行类似的操作
List<String> stringList = mapper.readValue(s, new TypeReference<List<POJO>>() {});
它将编译没有错误。但在运行时,一切都可能会中断。