gpt4 book ai didi

java - 如果存在特定字段,是否可以使用 Jackson 多态反序列化来序列化为子类型?

转载 作者:搜寻专家 更新时间:2023-10-30 19:47:36 25 4
gpt4 key购买 nike

使用旋转动物园示例:

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 是否会在以后正确序列化。

看来我可以使用自己的 TypeResolverTypeIdResolver ,但这似乎比我自己反序列化原始 json 还要多。此外,TypeResolverTypeIdResolver 似乎在本质上假定类型信息是序列化的,因此它们不适合使用。

实现我自己的 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com