【问题标题】:Serialzing heterogeneous collection with Jackson in Java在 Java 中使用 Jackson 序列化异构集合
【发布时间】:2016-08-15 03:43:00
【问题描述】:

我正在使用 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 有“类型”,Source 有“名称”。

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

    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"
} ]

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

【问题讨论】:

  • 绝对不是重复的,因为另一个问题不涉及集合类。
  • 正如您所注意到的,问题在于“输出 JSON 没有任何指示什么类型的对象被序列化”。这正是链接问题的意义所在,因此它的答案也解决了您的问题。
  • 好的,实际上它只包含大部分的答案。所以我会写剩下的。

标签: java json serialization jackson


【解决方案1】:

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

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

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

  2. @JsonTypeInfo 注释Base(例如@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class"))。为了使这个与集合一起工作,你还需要告诉杰克逊你想要存储一个List&lt;Base&gt;(参见第 5 节):

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

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

【讨论】:

    【解决方案2】:

    我的代码已经开始工作了。

    一开始我以为可以用WRAP_ROOT_VALUE来获取班级信息:

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

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

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

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

    这让序列化程序写入一个“类”属性,其中包含类值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-04-01
      • 1970-01-01
      • 1970-01-01
      • 2016-01-26
      • 1970-01-01
      • 1970-01-01
      • 2013-03-09
      相关资源
      最近更新 更多