用Java在Java中串行异构集合

时间:2016-04-21 18:49:11

标签: java json serialization jackson

我使用Jackson来序列化异构列表。我的列表声明如下:

   List<Base> myList = new LinkedList<>();

我在那里有课程AggregateSource

    myList.add(new Aggregate("count"));
    myList.add(new Aggregate("group"));
    myList.add(new Source("reader"));

这些类都实现了Base接口。每个类只有一个带get / set方法的属性:Aggregate有&#34; type&#34;,Source有&#34; name&#34;。

我使用此代码尝试序列化列表:

    ObjectMapper om = new ObjectMapper();
    om.configure(SerializationFeature.INDENT_OUTPUT, true);

    StringWriter c = new StringWriter();
    om.writeValue(c, myList);
    System.out.println(c);

但是我发现输出JSON没有任何关于序列化对象类型的指示:

[ {
  "type" : "count"
}, {
  "type" : "group"
}, {
  "name" : "reader"
} ]

因此,我不认为我可以对流进行反序列化并使其按预期工作。如何在异构集合中包含每个对象的序列化表示的类信息,以便可以正确地反序列化集合?

2 个答案:

答案 0 :(得分:0)

这在http://wiki.fasterxml.com/JacksonPolymorphicDeserialization中有详细描述。阅读它,但这里是最相关的部分。

要包含元素的类型信息,请参阅第1节。有两种选择:

  1. om.enableDefaultTyping()将存储存储为Object或抽象类型(包括接口)的元素的类名。请参阅过载文档。这将自动与集合一起使用。

  2. 使用Base注释@JsonTypeInfo(例如@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class"))。要使这个与集合一起使用,您还需要告诉杰克逊您想要存储List<Base>(并参见第5节):

    om.writerWithType(new TypeReference<List<Base>>() {}).writeValue(...); 
    

    JavaType listBase = objectMapper.constructCollectionType(List.class, Base.class);
    om.writerWithType(listBase).writeValue(...);
    

答案 1 :(得分:0)

我的代码工作正常。

起初,我以为我可以使用WRAP_ROOT_VALUE来获取课程信息:

   om.writer().with(SerializationFeature.WRAP_ROOT_VALUE).writeValue(c, myList);

这不起作用,因为它只使根项目具有类信息,而不是其他任何东西。我希望它会递归应用。

所以我不得不 直接使用List<>退出并将我的List<>对象包装在自己的类中。然后,基接口需要一个装饰来告诉它写类信息:

@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include= JsonTypeInfo.As.PROPERTY, property="class")
public interface Base {
}

这使序列化程序编写了一个&#34;类&#34;具有类值的属性。