- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
使用旋转动物园示例:
public class ZooPen {
public String type;
public List<Animal> animals;
}
public class Animal {
public String name;
public int age;
}
public class Bird extends Animal {
public double wingspan;
}
如果未指定翼展,我想使用多态反序列化构造 Animal
实例,如果指定翼展,则构造 Bird
实例。在 Jackson 中,非类型化反序列化通常看起来像这样:
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "wingspan",
visible = true,
defaultImpl = Animal.class
)
@JsonSubTypes({
@Type(value = Bird.class, name = "bird")
})
public class Animal {
...
}
wingspan 值可以是任何值,如果没有特定的匹配值,Jackson 将退回到 defaultImpl 类。
我可能会使用@JsonCreator
:
@JsonCreator
public static Animal create(Map<String,Object> jsonMap)
throws JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
if (jsonMap.get("wingspan") == null) {
// Construct and return animal
} else {
// Construct and return bird
}
}
但是,我必须手动处理额外的值并抛出一致的异常,并且不清楚 Animal
是否会在以后正确序列化。
看来我可以使用自己的 TypeResolver
或 TypeIdResolver
,但这似乎比我自己反序列化原始 json 还要多。此外,TypeResolver
和 TypeIdResolver
似乎在本质上假定类型信息是序列化的,因此它们不适合使用。
实现我自己的 JsonDeserializer
是否可行? Hook 到生命周期以指定类型,但仍使用基本的 Jackson 注释处理功能?我一直在看 JsonDeserializer.deserializeWithType(...)
,但这似乎将反序列化完全委托(delegate)给 TypeDeserializer
。还有一个问题是,在我知道要使用哪种类型之前,我需要反序列化一些对象。
或者,可能有一种方法可以定位动物园围栏的类型,即使它在父对象中也是如此。
有没有办法通过多态类型处理来完成我想做的事情?
最佳答案
从 Jackson 2.12.2 开始,以下内容使用“deduction-based polymorphism”功能实现了目标。如果存在不同于 Bird
子类型(即 wingspan
)的属性,则反序列化类型将为 Bird
;否则它将是 Animal
:
@JsonTypeInfo(use=Id.DEDUCTION, defaultImpl = Animal.class)
@JsonSubTypes({@Type(Bird.class)})
public class Animal {
public String name;
public int age;
}
基于推导的多态性特征根据与特定子类型不同的属性的存在来推导子类型。如果没有子类型特定属性可唯一标识的子类型,则将使用 defaultImpl
值指定的类型。
根据 jackson-databind#43 实现了基于推导的多态性功能在 Jackson 2.12 中,并在 2.12 release notes 中进行了总结:
It basically allows omitting of actual Type Id field or value, as long as the subtype can be deduced (
@JsonTypeInfo(use=DEDUCTION)
) from existence of fields. That is, every subtype has a distinct set of fields they included, and so during deserialization type can be uniquely and reliably detected.
这种在没有唯一可识别子类型时指定默认类型而不是抛出异常的能力是由 jackson-databind#3055 添加的在 jackson 2.12.2 中:
In the absence of a single candidate,
defaultImpl
should be the target type regardless of suitability.
在 Jackson 2.12 Most Wanted (1/5):Deduction-Based Polymorphism 中给出了基于推导的多态性的稍微长一点的解释。 jackson 创作者撰写的文章。
关于java - 如果存在特定字段,是否可以使用 Jackson 多态反序列化来序列化为子类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16488951/
我来自 Asp.Net 世界,试图理解 Angular State 的含义。 什么是 Angular 状态?它类似于Asp.Net中的ascx组件吗?是子页面吗?它类似于工作流程状态吗? 我听到很多人
我一直在寻找 3 态拨动开关,但运气不佳。 基本上我需要一个具有以下状态的开关: |开 |不适用 |关 | slider 默认从中间开始,一旦用户向左或向右滑动,就无法回到N/A(未回答)状态。 有人
我是一名优秀的程序员,十分优秀!