A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

前言
最近在公司项目中遇到了多态序列化异常的问题,具体详情如下:
[Java] 纯文本查看 复制代码
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这个类,接口代码如下:
[Java] 纯文本查看 复制代码
	//隐去了请求url和类型
    @ApiOperation("添加收款方式")
    public ResultInfo<? extends Payment> createPayment(
            @RequestBody Payment req) {

        return ResultInfo.success(xx.createPayment(req));
    }
解决方法如下:
[Java] 纯文本查看 复制代码
//在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在子类上制定)



转自掘金链接:https://juejin.im/post/5e951c5b6fb9a03c37304176





169 个回复

倒序浏览
感谢分享哦~
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报
大安 发表于 2020-4-20 11:10
棒棒哒  坚持更新哦

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报

努力呀,加油呀
回复 使用道具 举报
大安 发表于 2020-4-20 11:10
棒棒哒  坚持更新哦

努力呀,加油呀
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马