我有一个基类和一个派生类,如下面的
@JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS,
include =JsonTypeInfo.As.PROPERTY, property = "_type")
@JsonSubTypes({ @JsonSubTypes.Type(value = BaseClass.class,
name = "BaseClass")})
public class BaseClass{
private String a;
}
public class DerivedClass extends BaseClass{
private String b;
}
当我序列化BaseClass列表或DerivedClass列表时,我在json中找不到'_type'属性。但是如果我序列化一个BaseClass或Derived类的实例,我可以看到'_type'属性。
这是我的Serializer代码。
public void serialize() throws Exception {
List<DerivedClass> bs = new ArrayList<DerivedClass>();
bs.add(new DerivedClass());
bs.add(new DerivedClass());
String json = new ObjectMapper().writeValueAsString(bs);
LOG.debug(json);
}
答案 0 :(得分:1)
问题在于,由于Java Type Erasure,所有Jackson看到的都是List<Object>
,关于类型。由于Object
没有@JsonTypeInfo
,因此不认为需要类型信息 - 所有值必须使用相同的逻辑基类型,因为在反序列化期间没有实例,并且必须使用静态已知的类型作为基线
那么你如何解决这个问题?
首先:我的建议是始终使用简单的非通用POJO作为根值,并完全避免这个问题。从POJO到达的任何List
值属性都将具有完整的类型信息;根值不。因此,我避免直接序列化List
和Map
以及通用(参数化)POJO。
但是,如果您仍想解决更难的问题,那么它也是可行的。两种主要方式:
第一种方法:创建一个便利类,如:
public class ListOfBase extends ArrayList<BaseClass> { }
ListOfBase myList = new ListOfBase();
myList.add(...);
它将按预期工作,具有类型信息
第二种方法:强制使用特定的基本类型,通过ObjectWriter
:类似于:
ObjectWriter w = mapper.writerFor(new TypeReference<List<BaseClass>>() { });
String json = w.writeValueAsString(myList);
但是(不幸的是)这会强制使用BaseClass
来获取实际内容,而不仅仅是输入信息。因此,不包括任何实现类的属性。
实际上,还有第三种选择:使用Java数组,而不是集合。 数组是强类型的,所以这也可以工作:
BaseClass[] stuff = new BaseClass[] { value1, value2 };
因为类型信息被保留,与通用List
s不同。