前言
最近在公司项目中遇到了多态序列化异常的问题,具体详情如下:
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 @JsonSubTypes @JsonTypeName
use: 在序列化时标志出不同的类型用什么区分,用在反序列化时转换成响应的类型
JsonTypeInfo.Id.CLASS JsonTypeInfo.Id.MINIMAL_CLASS JsonTypeInfo.Id.NAME JsonTypeInfo.Id.NONE
include(可选):包含类型元数据的一种机制,指定识别码是如何被包含进去的,它有下面几个可选值:
JsonTypeInfo.As.PROPERTY JsonTypeInfo.As.EXISTING_PROPERTY 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