java - 序列化多态对象列表时未设置类型 ID 字段

标签 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 时,生成的 json 中不包含任何类型字段。但是,如果我使用 Animal[] 代替,则生成的 json 中将包含一个类型字段。在这两种情况下,反序列化工作正常,即。使用正确的子类。有人可以解释一下这种行为的原因吗?

最佳答案

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

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

参见this GitHub issue了解更多关于为什么这是必要的细节。

关于java - 序列化多态对象列表时未设置类型 ID 字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35714346/

相关文章:

C# 使用 JavaScriptSerializer.DeserializeObject 反序列化 JSON

java - 如何忽略 XStream 的类型?

java - 如何检查(甚至设置)mdb(ms access)文件中的排序规则?

java - 滑动时加速列表滚动 - Android。如何?

java - 我需要解析java中不同数据类型的其他集合中的集合内容

javascript - 爸爸解析 : Save JSON Output Locally

java - 编译代码出错

c++ - 在 C++ 中使用序列化模拟对象进行单元测试

java - 可打包对象中的数组列表

java - 需要帮助从完整的 JSON 数组/对象中提取字符串