杰克逊JSON多态性
我一直在尝试应用http://programmerbruce.blogspot.com/2011/05/deserialize-json-with-jackson-into.html)\,并将其应用于我一直在努力的方面。虽然它对JSON结构中所谓的“外部”元素非常有用,但我遇到了一个令人沮丧的问题,那就是没有太多的文档。杰克逊JSON多态性
首先,我的代码有点像下面这样:
interface Parameters {
// Couple random properties -- no problem here
SubTypeParameters getSubTypeParameters(); // where SubTypeParameters are polymorphic
void setSubTypeParameters(SubTypeParameters value);
}
@JsonSubTypes({
@JsonSubTypes.Type(name = "a", value = ASubTypeParameters.class),
@JsonSubTypes.Type(name = "b", value = BSubTypeParameters.class)
})
interface SubTypeParameters {
String getValue();
void setValue(String value);
}
@JsonTypeName(value = "a")
class ASubTypeParameters implements SubTypeParameters {
// getter/setter implemented
}
@JsonTypeName(value = "b")
class BSubTypeParameters implements SubTypeParameters {
// getter/setter implemented
}
我试图做的是落实在链接的博客帖子6号选项,以便JSON会出现如下内容(公告没有 '类型' 指定元件 - 它基于关闭上下文):
{
// other properties corresponding to the Parameters object
"a": {
"value": "value for a"
}
}
或
{
// other properties corresponding to the Parameters object
"b": {
"value": "value for b"
}
}
我试图避免的是向JSON对象中引入另一个“类型”变量。相反,我更愿意使用提供给上述任何一个JSON示例的上下文来知道我应该基于“a”或“b”的存在构建一个ASubTypeParameters或BSubTypeParameters对象。
的有趣的事情是,参数类/对象也多态,所以我已经注册了自己的自定义解串器类如下所示:
ObjectMapper mapper = new ObjectMapper();
StdDeserializer<Parameters> parameterDeserializer = new ParameterDeserializer();
SimpleModule module = new SimpleModule (...); // simplifying this--no problem here
module.addDeserializer(Parameters.class, parameterDeserializer);
mapper.registerModule(module);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
然而,当上述解串器试图反序列化任一以上的JSON示例,它会到达它试图反序列化“a”或“b”的部分,并指示它不知道如何处理这些属性(如果我移除未知属性行上的失败,则为UnrecognizedPropretyException)。我的问题真的归结为:我错过了什么(注释或其他)?
我也尝试添加:
mapper.registerSubtypes(ASubTypeParameters.class, BSubTypeParameters.class)
以及
mapper.registerSubtypes(
new NamedType(ASubTypeParameters.class, "a"),
new NamedType(BSubTypeParameters.class, "b")
);
无济于事。
我知道我越来越接近了,我的猜测是我需要编写某种自定义子类型处理程序,但文档似乎缺少我想要做的事情(特别是当您反序列化也包含多态元素的多态类型/类)。
使用Jackson,您可以配置使用以下注释将类型信息存储为单个字段的名称:@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT)
。结果应该看起来像你的JSON例子。
我稍微修改代码来证明它:
public class JacksonPolymorphic2 {
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include=JsonTypeInfo.As.WRAPPER_OBJECT)
@JsonSubTypes({
@JsonSubTypes.Type(name = "a", value = ASubTypeParameters.class),
@JsonSubTypes.Type(name = "b", value = BSubTypeParameters.class)
})
interface SubTypeParameters {
String getValue();
void setValue(String value);
}
@JsonTypeName(value = "a")
static class ASubTypeParameters implements SubTypeParameters {
ASubTypeParameters(String value) {
this.value = value;
}
private String value;
@Override
public String getValue() {
return value;
}
@Override
public void setValue(String value) {
this.value = value;
}
}
@JsonTypeName(value = "b")
static class BSubTypeParameters implements SubTypeParameters {
BSubTypeParameters(String value) {
this.value = value;
}
private String value;
@Override
public String getValue() {
return value;
}
@Override
public void setValue(String value) {
this.value = value;
}
}
public static void main(String[] args) throws JsonProcessingException {
ASubTypeParameters a = new ASubTypeParameters("aType");
BSubTypeParameters b = new BSubTypeParameters("bType");
List<? super SubTypeParameters> list = new ArrayList<>();
list.add(a);
list.add(b);
ObjectMapper mapper = new ObjectMapper();
System.out.printf(mapper
.writerWithType(new TypeReference<List<SubTypeParameters>>() {})
.withDefaultPrettyPrinter()
.writeValueAsString(list));
}
}
输出:
[ {
"a" : {
"value" : "aType"
}
}, {
"b" : {
"value" : "bType"
}
} ]