我有一个具有通用集合字段的类
class Test {
List<E> aList;
}
我想使用杰克逊反序列化它。如何在不使用注释的情况下指定用于此特定字段的集合类型,而不是对象中的所有列表(因为我无法更改现有类)。
我是杰克逊的初学者,所以我不知道如何编写自定义反序列化器。
FWIW...
不使用注释(因为我无法更改现有类)
Jackson 的 Mix-Ins 功能可用于解决此问题。
我不知道如何编写自定义反序列化器
尽管没有完全更新最新的 Jackson 版本,但 Jackson Wiki 页面上关于自定义反序列化和自定义创建者的页面仍然相关。
此外,在Gson v Jackson - Part 3 on InstanceCreator for a Parameterized Type中,我针对类似问题发布了几个不同的解决方案。
我认为您不需要做任何事情 Jackson 似乎能够弄清楚 List 的数据类型,我上周遇到了这个问题,结果证明 Java Generic 信息可以通过反射获得,请参阅有什么例外在 Java 中键入擦除?和Java 中的类型擦除
我编写了以下测试程序以更好地理解它。
public class GenericObject {
public Map<Integer,String> map = new HashMap<>();
private List<Integer> integers = new ArrayList<>();
private List<Date> dates = new ArrayList<>();
public List<Integer> getIntegers() {
return integers;
}
public void setIntegers(List<Integer> integers) {
this.integers = integers;
}
public List<Date> getDates() {
return dates;
}
public void setDates(List<Date> dates) {
this.dates = dates;
}
public void setIntegersList(Integer... ints)
{
for (Integer integer : ints) {
integers.add(integer);
}
}
public void setDatesList(Date... dates)
{
for (Date date : dates) {
this.dates.add(date);
}
}
public void runtimeGenericTypes()
{
try {
Field field = GenericObject.class.getField("map");
System.out.println("Field has type " + field.getType());
ParameterizedType genericType = (ParameterizedType) field.getGenericType();
Type[] actualTypeArguments2 = genericType.getActualTypeArguments();
for (Type type : actualTypeArguments2) {
System.out.println("Gerenic field types: " + type);
}
// get the return type of a generic method
Method method =GenericObject.class.getMethod("getIntegers",null);
Class<?> returnType = method.getReturnType();
System.out.println(returnType);
Type genericReturnType = method.getGenericReturnType();
ParameterizedType parameterizedType = (ParameterizedType) genericReturnType;
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
for (Type type : actualTypeArguments) {
System.out.println(type);
}
System.out.println(genericReturnType);
// get the parameter type of a generic method
Method set = GenericObject.class.getMethod("setIntegers", List.class);
Class<?>[] parameterTypes = set.getParameterTypes();
for (Class<?> class1 : parameterTypes) {
System.out.println("Parameter type " + class1);
}
Type[] genericParameterTypes = set.getGenericParameterTypes();
for (Type type : genericParameterTypes) {
ParameterizedType parameterizedType2 = (ParameterizedType) type;
parameterizedType2.getActualTypeArguments();
for (Type type2 : genericParameterTypes) {
System.out.println(" Paratermer type is: " + type2);
}
}
} catch (SecurityException | NoSuchMethodException | NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
TypeVariable<?>[] typeParameters = dates.getClass().getTypeParameters();
for (TypeVariable<?> typeVariable : typeParameters) {
System.out.println(typeVariable);
}
}
public static void main(String[] args) {
GenericObject object = new GenericObject();
object.setIntegersList(1,2,4,5,5);
object.setDatesList(new Date());
object.runtimeGenericTypes();
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT,true);
DateFormat df = DateFormat.getDateInstance(DateFormat.LONG);
mapper.setDateFormat(df);
String json;
try {
json = mapper.writeValueAsString(object);
System.out.println(json);
GenericObject readObject = mapper.readValue(json, GenericObject.class);
List<Integer> readIntegers = readObject.getIntegers();
for (Integer integer : readIntegers) {
System.out.println(integer);
}
List<Date> dates2 = readObject.getDates();
for (Date date : dates2) {
System.out.println(date);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}