前言
最近在公司项目中遇到了多态序列化异常的问题,具体详情如下:
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