JDr*_*818 5 java class list type-erasure jackson
多年来,我一直在使用 Jackson 来序列化/反序列化对象,并且总是发现使用TypeReference<T>
反序列化List
等不必要地复杂。我创建了一个简单的辅助函数:
public static <T> TypeReference<List<T>> list() {
return new TypeReference<List<T>>(){}
}
Run Code Online (Sandbox Code Playgroud)
预期用途:
List<Foo> foos = objectMapper.readValue(json, list());
Run Code Online (Sandbox Code Playgroud)
它有效!的种类。通过调试器进行检查时,不是 的列表Foo
,而是 的列表LinkedHashMap
。我知道ObjectMapper
反序列化为LinkedHashMap
类型Object
,我在这里阅读了解释:
但是,为什么它能够分配List<LinkedHasMap>
给 a List<Foo>
?至少不应该是某种ClassCastException
吗?
另外,有没有办法用Java的类型系统来做到这一点?
注意:以下方法声明具有相同的问题,这是有道理的,因为不需要T
确定附加参数:
public static <T> TypeReference<List<T>> listOf(Class<T> ignored) {
return new TypeReference<List<T>>(){}
}
Run Code Online (Sandbox Code Playgroud)
Mic*_*ber 12
由于Java 中的类型擦除,它的工作原理如下。请在开始阅读本答案的下一部分之前先阅读以下内容:
您现在可能知道,阅读完上述文章后,编译后的方法如下所示:
static <T> TypeReference<List> listOf(Class<T> ignored) {
return new TypeReference<List>(){};
}
Run Code Online (Sandbox Code Playgroud)
Jackson 将尝试找出最适合它的java.util.LinkedHashMap
JSON 对象类型。要创建无可辩驳的类型,您需要使用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;
// getters, setters, toString
}
Run Code Online (Sandbox Code Playgroud)
上面的示例,对于以下JSON
有效负载:
static <T> TypeReference<List> listOf(Class<T> ignored) {
return new TypeReference<List>(){};
}
Run Code Online (Sandbox Code Playgroud)
印刷:
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;
// getters, setters, toString
}
Run Code Online (Sandbox Code Playgroud)
也可以看看:
归档时间: |
|
查看次数: |
3506 次 |
最近记录: |