这是因为Java中的类型擦除。在阅读本答案的下一部分之前,请先阅读相关内容:
- [类型擦除](link1)
- [解释Java中的类型擦除](link2)
- [Java泛型类型擦除:何时以及发生了什么?](link3)
在阅读上述文章后,你可能已经知道,编译后的方法看起来像这样:
static <T> TypeReference<List> listOf(Class<T> ignored) {
return new TypeReference<List>(){};
}
Jackson会尝试找到最适合的类型,对于一个JSON对象来说,最适合的类型将是
java.util.LinkedHashMap
。要创建一个不可否认的类型,您需要使用
com.fasterxml.jackson.databind.type.TypeFactory
类。请参考下面的示例:
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.TypeFactory;
import java.io.File;
import java.util.List;
public class JsonTypeApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
System.out.println("Try with 'TypeFactory'");
List<Id> ids = mapper.readValue(jsonFile, CollectionsTypeFactory.listOf(Id.class));
System.out.println(ids);
Id id1 = ids.get(0);
System.out.println(id1);
System.out.println("Try with 'TypeReference<List<T>>'");
List<Id> maps = mapper.readValue(jsonFile, CollectionsTypeFactory.erasedListOf(Id.class));
System.out.println(maps);
Id maps1 = maps.get(0);
System.out.println(maps1);
}
}
class CollectionsTypeFactory {
static JavaType listOf(Class clazz) {
return TypeFactory.defaultInstance().constructCollectionType(List.class, clazz);
}
static <T> TypeReference<List> erasedListOf(Class<T> ignored) {
return new TypeReference<List>(){};
}
}
class Id {
private int id;
}
以上示例,针对以下
JSON
负载:
[
{
"id": 1
},
{
"id": 22
},
{
"id": 333
}
]
打印:
Try with 'TypeFactory'
[{1}, {22}, {333}]
{1}
Try with 'TypeReference<List<T>>'
[{id=1}, {id=22}, {id=333}]
Exception in thread "main" java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to com.example.Id
at com.example.JsonTypeApp.main(JsonTypeApp.java:27)
另请参阅:
List<LinkedHasMap>
和List<Foo>
没有区别,因为存在类型擦除。 - Savior