在没有注释的情况下指定Jackson中特定通用集合字段的具体类型

时间:2012-08-08 09:02:58

标签: java json jackson

我有一个具有通用集合字段的类

class Test {
  List<E> aList;
}

我想用杰克逊反序化这个。如何在不使用注释的情况下指定要用于此特定字段的集合类型,而不是对象中的所有列表(因为我无法更改现有类)。

我是杰克逊的初学者,所以我不知道如何编写自定义反序列化器。

2 个答案:

答案 0 :(得分:1)

... FWIW

  

不使用注释(因为我无法更改现有的类)

Jackson's Mix-Ins feature可用于解决此问题。

  

我不知道如何编写自定义反序列化器

尽管与最新的杰克逊版本不完全一致,custom deserializationcustom creators上的杰克逊维基页面仍然相关。

此外,在Gson v Jackson - Part 3 on InstanceCreator for a Parameterized Type中,我针对类似问题发布了几种不同的解决方案。

答案 1 :(得分:0)

我认为你不需要做任何事杰克逊似乎能够弄清楚List的数据类型,我上周遇到了这个问题,结果发现Java Generic信息可以通过反射看到{ {3}}和What are the exceptions to type erasure in 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();
        }


}

}