我正在使用杰克逊来序列化异构列表。我的列表声明如下:
List<Base> myList = new LinkedList<>();
我有Aggregate
和Source
的课程:
myList.add(new Aggregate("count"));
myList.add(new Aggregate("group"));
myList.add(new Source("reader"));
这些类都实现Base
接口。每个类只有一个带有 get/set 方法的属性:Aggregate
有"类型",Source
有"name"。
我使用此代码尝试序列化列表:
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"
} ]
因此,我认为我不可能反序列化流并让它按预期工作。如何包含有关异类集合中每个对象的序列化表示形式的类信息,以便可以正确反序列化集合?
在 http://wiki.fasterxml.com/JacksonPolymorphicDeserialization 中有确切的描述。阅读它,但这是最相关的部分。
要包含元素的类型信息,请参阅第 1 节。有两种选择:
om.enableDefaultTyping()
将存储存储为Object
或抽象类型(包括接口)的元素的类名。有关重载,请参阅文档。这将自动处理集合。用
@JsonTypeInfo
注释Base
(例如@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
)。要使这适用于集合,您还需要告诉 Jackson 您想要存储List<Base>
(请参阅第 5 节):om.writerWithType(new TypeReference<List<Base>>() {}).writeValue(...);
或
JavaType listBase = objectMapper.constructCollectionType(List.class, Base.class); om.writerWithType(listBase).writeValue(...);
的代码工作了。
起初,我以为我可以使用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 {
}
这会让序列化程序编写一个包含类值的"class"属性。