我有一个抽象的超类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 {
但那没用。这有什么例子吗?如何告诉对象映射器使用我的注释?任何这方面的例子都很棒。
答案 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
让杰克逊找到它们。)