如果我有一个这样的类结构:
public abstract class Parent {
private Long id;
...
}
public class SubClassA extends Parent {
private String stringA;
private Integer intA;
...
}
public class SubClassB extends Parent {
private String stringB;
private Integer intB;
...
}
是否有其他方法可以反序列化不同的@JsonTypeInfo
?在我的父类上使用这个注解:
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "objectType")
我宁愿不强制API的客户端包含"objectType": "SubClassA"
来反序列化Parent
子类。
Jackson没有使用@JsonTypeInfo
,而是提供了一种注解子类的方法,并通过唯一属性将其与其他子类区分开来吗?在我上面的例子中,这将是类似于“如果JSON对象具有"stringA": ...
,则将其反序列化为SubClassA
,如果它具有"stringB": ...
,则将其反序列化为SubClassB
”。
8条答案
按热度按时间wnrlj8wa1#
这里有一个解决方案,我想出了一个扩展了埃里克吉莱斯皮的一点。它完全符合你的要求,对我很有效。
使用Jackson2.9
如果您想更进一步,可以扩展
CustomDeserializer
以包含一个Map<String, Class<?>>
,该Map<String, Class<?>>
Map一个属性名,该属性名在出现时Map到一个特定的类。在这个article中提出了这样的方法。更新
Jackson2.12.0获得了Polymorphic subtype deduction from available fields,增加了
@JsonTypeInfo(use = DEDUCTION)
!AsDeductionTypeDeserializer实现从字段中推断子类型。作为一个POC不打算合并,有大量的剪切和粘贴代码等,但我认为一个功能性的公关将是最好的基础上讨论的东西,我写的兴趣。
它的工作原理是在注册时对每个子类型的全部可能字段进行指纹识别。在反序列化时,将可用字段与那些指纹进行比较,直到仅剩下一个候选者。它只关注直接子字段名称,因为直接子值被现有机制所覆盖,更深入的分析是一项更艰巨的ML任务,而不是Jackson的职责。
顺便说一句,这里有一个(现已关闭)Github问题请求:https://github.com/FasterXML/jackson-databind/issues/1627
vawmfj5a2#
这感觉像是应该使用
@JsonTypeInfo
和@JsonSubTypes
的东西,但是我已经通过文档挑选了,没有一个可以提供的属性似乎与您所描述的完全匹配。您可以编写一个自定义的反序列化器,它以非标准的方式使用
@JsonSubTypes
的“name”和“value”属性来实现您想要的功能。反序列化器和@JsonSubTypes
将在基类上提供,反序列化器将使用“name”值来检查属性的存在,如果它存在,则将JSON反序列化为“value”属性中提供的类。你的类看起来像这样:6za6bjd03#
正如其他人指出的那样,在how it should work so it hasn't been implemented上没有达成共识。
如果你有类Foo,Bar和它们的父FooBar解决方案,当你有JSON时,似乎很明显:
或
但是当你被一个
乍一看,最后一个例子似乎是一个明显的400 Bad Request案例,但实际上有许多不同的方法:
1.处理为400 Bad Request
1.按类型/字段的优先级(例如,如果存在字段错误,则其优先级高于其他字段foo)
1.更复杂的情况2。
我目前的解决方案适用于大多数情况,并试图尽可能多地利用现有的Jackson基础设施(每个层次结构只需要1个反序列化器):
示例用法:
Jackson构型
如果你正在使用Sping Boot :
测试:
编辑:我在这个project中添加了对这种情况的支持。
2sbarzqh4#
EDIT(2021-07-15)--作废,目前状态见M. Justin's answer。
(以下为原始答案)
没有。这样的特性已经被要求了--它可以被称为“类型推断”,或者“隐含类型”--但是还没有人提出一个可行的通用建议来说明它应该如何工作。很容易想到方法来支持特定情况下的特定解决方案,但找出一般的解决方案就比较困难了。
lzfw57am5#
此功能已使用“deduction-based polymorphism”添加到Jackson2.12中。要将其应用于您的案例,只需使用
@JsonTypeInfo(use=Id.DEDUCTION)
以及@JsonSubTypes
提供的支持的子类型的完整列表:此功能是根据jackson-databind#43实现的,并在2.12发行说明中进行了总结:
它基本上允许省略实际的Type Id字段或值,只要可以从字段的存在推断出子类型(
@JsonTypeInfo(use=DEDUCTION)
)。也就是说,每个子类型都包含一组不同的字段,因此在反序列化期间,可以唯一且可靠地检测类型。Jackson的创作者在Jackson 2.12 Most Wanted (1/5): Deduction-Based Polymorphism文章中给出了一个稍微长一点的解释。
8iwquhpp6#
我的应用程序要求我保留旧的结构,所以我找到了一种在不更改数据的情况下支持多态性的方法。我是这么做的
1.扩展JsonDeserializer
1.转换为树并读取字段,然后返回子类对象
eagi6jfj7#
处理多态要么是模型绑定的,要么需要使用各种自定义反序列化器编写大量代码。我是一个JSON Dynamic Deserialization Library的合著者,它允许模型独立的json反序列化库。OP问题的解决方案可以在下面找到。请注意,规则是以非常简短的方式声明的。
输出:
pretius-jddl的Maven依赖关系(在maven.org/jddl上查看最新版本:
iq3niunx8#
已经看到上面的几个答案,但我想添加我的,因为这是在生产中使用了过去2年。
我们有一个事件类型的速度,位置的车辆。
可以通过@JsonTypeInfo实现动态绑定
示例输出:-
速度事件
地点事件