转载

记录多态如何序列化与反序列化

前言

最近在公司项目中遇到了多态序列化异常的问题,具体详情如下:

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

在上述资料中,解决多态最关键的注解就是@JsonTypeInfo

  • 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,此属性只有当:

    • useJsonTypeInfo.Id.CLASS (若不指定property则默认为@class)、 JsonTypeInfo.Id.MINIMAL_CLASS (若不指定property则默认为@class)、 JsonTypeInfo.Id.NAME (若不指定property默认为@type),
    • includeJsonTypeInfo.As.PROPERTYJsonTypeInfo.As.EXISTING_PROPERTYJsonTypeInfo.As.EXTERNAL_PROPERTY 时才有效
  • defaultImpl(可选):如果类型识别码不存在或者无效,可以使用该属性来制定反序列化时使用的默认类型

  • visible(可选):是否可见(默认false)属性定义了类型标识符的值是否会通过JSON流成为反序列化器的一部分,默认为fale,也就是说,jackson会从JSON内容中处理和删除类型标识符再传递给JsonDeserializer

原文  https://juejin.im/post/5e951c5b6fb9a03c37304176
正文到此结束
Loading...