前言
最近在公司项目中遇到了多态序列化异常的问题,具体详情如下:
org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class com.x.x.x.Payment]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.x.x.x.Payment` (no Creators, like default construct, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
复制代码
项目中需要用户添加自己的收款方式,而收款方式又分为ABC三种, 继承了Payment这个类,接口代码如下:
//隐去了请求url和类型
@ApiOperation("添加收款方式")
public ResultInfo<? extends Payment> createPayment(
@RequestBody Payment req) {
return ResultInfo.success(xx.createPayment(req));
}
复制代码
解决方法如下:
//在Payment类上加上这些信息
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.EXISTING_PROPERTY,
property = "payment"
)
@JsonSubTypes(value = {
@JsonSubTypes.Type(value = A.class, name = "A"),
@JsonSubTypes.Type(value = B.class, name = "B"),
@JsonSubTypes.Type(value = C.class, name = "C")
})
public class Payment {
//具体字段我就不写了
}
复制代码
查阅网上资料可得
@JsonTypeInfo
– indicates details of what type information to include in serialization 指出序列化包含的类型信息细节@JsonSubTypes
– indicates sub-types of the annotated type 指出被注解类型的子类@JsonTypeName
– defines a logical type name to use for annotated class 定义被注解类使用的逻辑名称
在上述资料中,解决多态最关键的注解就是@JsonTypeInfo
-
use: 在序列化时标志出不同的类型用什么区分,用在反序列化时转换成响应的类型
JsonTypeInfo.Id.CLASS
:使用完全限定类名做识别JsonTypeInfo.Id.MINIMAL_CLASS
:若父类和子类在同一包类,使用类名(忽略包名)作为识别码JsonTypeInfo.Id.NAME
:一个合乎逻辑的指定名称JsonTypeInfo.Id.NONE
:不使用识别码
-
include(可选):包含类型元数据的一种机制,指定识别码是如何被包含进去的,它有下面几个可选值:
JsonTypeInfo.As.PROPERTY
:作为数据的兄弟属性JsonTypeInfo.As.EXISTING_PROPERTY
:作为POJO中已经存在的属性JsonTypeInfo.As.EXTERNAL_PROPERTY
:作为扩展属性JsonTypeInfo.As.WRAPPER_OBJECT
:作为一个包装的对象JsonTypeInfo.As.WRAPPER_ARRAY
:作为一个包装的数组
-
property(可选):自定义的区分类型的id,默认是@Class,此属性只有当:
use
为JsonTypeInfo.Id.CLASS
(若不指定property则默认为@class)、JsonTypeInfo.Id.MINIMAL_CLASS
(若不指定property则默认为@class)、JsonTypeInfo.Id.NAME
(若不指定property默认为@type),include
为JsonTypeInfo.As.PROPERTY
、JsonTypeInfo.As.EXISTING_PROPERTY
、JsonTypeInfo.As.EXTERNAL_PROPERTY
时才有效
-
defaultImpl(可选):如果类型识别码不存在或者无效,可以使用该属性来制定反序列化时使用的默认类型
-
visible(可选):是否可见(默认false)属性定义了类型标识符的值是否会通过JSON流成为反序列化器的一部分,默认为fale,也就是说,jackson会从JSON内容中处理和删除类型标识符再传递给JsonDeserializer
@JsonSubTypes
作用于类/接口,用来列出给定类的子类,只有当子类类型无法被检测到时才会使用它,一般是配合@JsonTypeInfo在基类上使用。 @JsonSubTypes
的值是一个@JsonSubTypes.Type[]
数组,里面枚举了多态类型(value对应子类)和类型的标识符值(name对应@JsonTypeInfo
中的property标识名称的值,此为可选值,若不制定需由@JsonTypeName
在子类上制定)
有机会再来完善更多内容吧
- 文章参考: