在序列化多态对象列表时,未设置类型Id字段

时间:2016-03-01 03:54:59

标签: java json serialization jackson

考虑一下我写的这段代码,用于Jackson对多态序列化/反序列化的支持(http://wiki.fasterxml.com/JacksonPolymorphicDeserialization) -

public class Main {

    @JsonTypeInfo(
        use=JsonTypeInfo.Id.NAME,
        include=JsonTypeInfo.As.PROPERTY,
        property="type")
    @JsonSubTypes({
        @JsonSubTypes.Type(name = "dog", value = Dog.class),
        @JsonSubTypes.Type(name = "cat", value = Cat.class)
    })
    public abstract static class Animal {
        public String name;
    }

    public static class Dog extends Animal {
        public int barkLevel;
    }

    public static class Cat extends Animal {
        public int meowLevel;
    }

    public static void main(String[] args) throws Exception {

        String marshalled = "" +
            "[\n" +
            "    {\n" +
            "       \"name\"      : \"cookie\",\n" +
            "       \"type\"      : \"dog\",\n" +
            "       \"barkLevel\" : 5\n" +
            "    },\n" +
            "    {\n" +
            "       \"name\"      : \"misty\",\n" +
            "       \"type\"      : \"cat\",\n" +
            "       \"meowLevel\" : 3\n" +
            "    }\n" +
            "]\n";

        ObjectMapper mapper = new ObjectMapper();
        mapper.enable(SerializationFeature.INDENT_OUTPUT);

        List<Animal> unmarshalledList = mapper.readValue(
            marshalled,
            new TypeReference<List<Animal>>() {}
        );

        Animal[] unmarshalledArray = mapper.readValue(
            marshalled,
            new TypeReference<Animal[]>() {}
        );

        for (Animal animal : unmarshalledList) {
            System.out.println(animal.getClass().getSimpleName());
        }
        System.out.println(
            mapper.writeValueAsString(
                unmarshalledList
            ) + "\n"
        );

        for (Animal animal : unmarshalledArray) {
            System.out.println(animal.getClass().getSimpleName());
        }
        System.out.println(
            mapper.writeValueAsString(
                unmarshalledArray
            )
        );
    }
}

它产生以下输出 -

Dog
Cat
[ {
  "name" : "cookie",
  "barkLevel" : 5
}, {
  "name" : "misty",
  "meowLevel" : 3
} ]

Dog
Cat
[ {
  "type" : "dog",
  "name" : "cookie",
  "barkLevel" : 5
}, {
  "type" : "cat",
  "name" : "misty",
  "meowLevel" : 3
} ]

我的问题是 - 当我序列化List&lt; Animal&gt;时,生成的json中不包含任何类型字段。但是,如果我使用Animal [],则生成的json中会包含一个类型字段。在这两种情况下,反序列化都可以正常工作,即。使用正确的子类。有人可以解释这种行为的原因吗?

1 个答案:

答案 0 :(得分:2)

要使用多态序列化序列化通用集合,您需要执行以下操作:

mapper.writerFor(new TypeReference<List<Animal>>() {}).writeValueAsString(unmarshalledList));

有关为何需要这些内容的详细信息,请参阅this GitHub issue