Jackson反序列化classImpl对象的List <abstract class> </abstract class>

时间:2014-03-27 23:04:06

标签: java json serialization jackson

我有一个抽象的超类A. 我有几个具体的sublasess B,C,D

在序列化方面,我这样做:

List<A> list = new ArrayList<A>();
B b = new B();
C c = new C();
D d = new D();
list.add(b);
list.add(c);
list.add(d);
json = mapper.writeValueAsString(list);

没问题。我想现在反序列化这个。我知道我无法实例化一个抽象类,所以这是如何完成的?

这不起作用:

list = mapper.readValue(json,new TypeReference<List<A>>() {});
编辑:我把它添加到我的抽象超类中:(仍然没有运气)

@JsonTypeInfo(use=JsonTypeInfo.Id.CLASS, include=JsonTypeInfo.As.PROPERTY, property="@class")
public abstract class A {

再次编辑:我现在收到此错误:

Unexpected token (END_OBJECT), expected FIELD_NAME: missing property '@class' that is to contain type id

查看JSON,@ class不在那里。我如何让它在那里? 我试过了:

@JsonDeserialize(as=B.class)
public class B extends A { 

但那没用。这有什么例子吗?如何告诉对象映射器使用我的注释?任何这方面的例子都很棒。

2 个答案:

答案 0 :(得分:0)

您已正确完成,但Jackson未检查集合中的元素。请看这个问题的答案:Error serializing Typed collection with Jackson。您必须使用特殊集合,Jackson将使用自定义序列化程序。

简单用法:

List<A> list = new JacksonList<>();
list.add(new B());
list.add(new C());

ObjectMapper mapper = new ObjectMapper();
String json = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(list);
System.out.println(json);
System.out.println(mapper.readValue(json, new TypeReference<List<A>>() {}));

答案 1 :(得分:0)

Java Type Erasure问题的常见解决方法(遗憾的是问题与Jackson相关的问题)与使用自定义子类型相似:

public class AList extends ArrayList<A> { }

并通过此;它确保有足够的类型信息可用于序列化和反序列化(因为问题是序列化几乎总是成功,因为对象可以使用类型;反序列化不是这样。)

除此之外,还有从抽象类型A到子类型的映射问题。

如果您只有一个实现,则可以使用SimpleModule和方法addAbstractTypeMapping(A.class, B.class)来指示要使用的默认实现。

但如果您需要其他子类型,则需要使用A注释@JsonTypeInfo,并使其使用Java类名或使用@JsonTypeName为子类指定类型名称(加上基类@JsonSubTypes让杰克逊找到它们。)