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 10:20:42
8#
66666666666666
回复 使用道具 举报
感谢分享
回复 使用道具 举报
感谢分享
回复 使用道具 举报

感谢分享哦~
回复 使用道具 举报
感谢分享
回复 使用道具 举报

感谢分享哦~
回复 使用道具 举报
锄禾我日当午, 汗滴这禾下土, 谁知那盘中餐, 粒粒他皆辛苦
回复 使用道具 举报
666666666666666666
回复 使用道具 举报
666666666666
回复 使用道具 举报
棒棒哒  坚持更新哦
回复 使用道具 举报

感谢分享哦~
回复 使用道具 举报

感谢分享哦~
回复 使用道具 举报
66666666666666666666666
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马