Jackson里使用@JsonTypeInfo注解处理多态类型的序列化和反序列化

问题场景

在将多态类型进行JSON序列化后,Jackson无法在反序列化期间找出正确的类型。
可以通过一个例子来理解它。

下面开始序列化和反序列化一个View实例

出现如下错误

使用@JsonTypeInfo

此注解用于序列化有关多态实例的实际类的信息,以便Jackson可以知道要反序列化的子类型。

可以使用以下注释来解决上面出现的异常:

上面的配置指定使用的类名称(use = JsonTypeInfo.Id.CLASS),并将其作为JSON属性保留(include = JsonTypeInfo.As.PROPERTY)。 属性名称应该是’className’。

再次运行我们的main方法:

在上述配置中,元素“ include”和“ property”都是可选的,不写将使用默认值。 默认的“ include”也是JsonTypeInfo.As.PROPERTY,默认的“ property”是@class。

所以,也可以这样写:

将被序列化为:

在属性上使用@JsonTypeInfo

@JsonTypeInfo注释可以在类(上面的示例)和属性上使用。

例如可以在’shapes’属性上使用注解:

如果该注解同时作用在类和属性上,则以使用在属性上的注解为准,因为它被认为更具体。

需要特别说明的是,当@JsonTypeInfo在属性(字段,方法)上使用时,此注解适用于值。 当在集合类型(List,Map,Array)上使用时,它将应用于元素,而不是集合本身。 对于非集合类型,没有区别。

也就是说,在上面的代码中,当我们将其用于“shapes”的list时,它是应用于list里的每个元素(shape),而不是list类型本身。

使用JsonTypeInfo.Id.MINIMAL_CLASS

use = JsonTypeInfo.Id.MINIMAL_CLASS选项将序列化最小的相对程序包路径。

还拿上面的例子来说,如果把use = JsonTypeInfo.Id.CLASS换成use = JsonTypeInfo.Id.MINIMAL_CLASS,那么序列化后的结果是

全局Default Typing机制

除了使用@JsonTypeInfo注解来实现多态数据绑定,还可以使用全局Default Typing机制。

DefaultTyping有四个选项

  • JAVA_LANG_OBJECT: 当对象属性类型为Object时生效
  • OBJECT_AND_NON_CONCRETE: 当对象属性类型为Object或者非具体类型(抽象类和接口)时生效
  • NON_CONCRETE_AND+_ARRAYS: 同上, 另外所有的数组元素的类型都是非具体类型或者对象类型
  • NON_FINAL: 对所有非final类型或者非final类型元素的数组

开启DefaultTyping,并且让所有的非final类型对象持久化时都存储类型信息显然能准确的反序列多态类型的数据。

具体实现,可以看这段代码

在上面的示例中,DefaultTyping.OBJECT_AND_NON_CONCRETE指定默认类型将用于声明类型为java.lang.Object或抽象类型(抽象类或接口,在我们的示例中为Shape)的属性。

请注意,在上面的输出中,List <Shape>的实际类型也作为ArrayList保留。 这是因为List也是non-concrete类型。

pom.xml

0

《Jackson里使用@JsonTypeInfo注解处理多态类型的序列化和反序列化》有一个想法

发表评论

邮箱地址不会被公开。