jackson序列化和反序列化,jackson反序列化泛型
00-1010场景Jackson多态类型序列化/反序列化摘要
00-1010是消息中心,负责发送消息。消息分为几个渠道,包括手机通知(Push)、短信(SMS)、邮件、Websocket等渠道。
我定义了一个基类MessageRequest来接收请求参数,代码如下:
公共类MessageRequest实现可序列化的{ protected MessageChannel通道;private message request(){ } protected message request(message channel channel){ this . channel=channel;} public message channel get channel(){ return this . channel;} } message request中有一个属性channel,是枚举MessageChannel。枚举枚举所有通道,代码如下:
公共枚举消息通道{ PUSH,EMAIL,WEBSOCKET,SMS,message channel(){ } } message request有各种通道的子类。以推送为例:
公共类PushMessageReuqest扩展了message request { public PushMessageRequest(){ super(message channel。推);}私有字符串标题;//省略其他字段和getter、setter方法.}我在接口中使用MessageRequest接收:
公共类message controller { @ post mapping(/sendMessage )公共对象sendMessage(message request request){ system . out . println(request);}}使用postman发送push请求后,发现后端收到的类型仍然是基类,title字段缺失。
这不是我所期望的,因为客户端知道通道,所以只需为我构建相应的通道消息!为什么铅字被擦掉了?我的想法是发送一个推送请求。后来才知道,序列化之后,不知道给你反序列化什么类型,序列化工具也不够智能,不能根据你的通道属性知道是什么类型,但是我又想这么做。那我该怎么办呢?
10-1010上,请教各位领导后发现了两个注解,@JsonTypeInfo和@JsonSubTypes。
@JsonTypeInfo作用于类/接口,用于打开多态类型处理。它有一些属性:
使用(必需):要定义使用哪种类型的识别码,有以下选项。无:不使用ID类:使用完全限定的类名作为ID。MINIMAL_CLASS:使用类名(忽略包名)作为ID。在与基类相同的包中,可以使用name:指定名称CUSTOM: custom ID,而@JsonTypeIdResolver对应include(可选):指定如何包含ID。有以下几种选择。property:作为兄弟属性添加,默认值WRAPPER_OBJECT: WRAPPER_ARRAY作为包装对象:EXTERNAL_PROPERTY作为包装数组:EXISTING_PROPERTY作为扩展属性:作为现有属性(符合我的场景,使用通道)PROPERTY(可选):指定识别码的属性名。该属性只能在use is CLASS(默认为@class),MINIMAL_C时使用
LASS(不指定默认为@c
)、NAME(不指定默认为@type
,include
为PROPERTY、EXISTING_PROPERTY、EXTERNAL_PROPERTY时才有效。defaultImpl(可选):如果类型识别码不存在或者无效,可以使用该属性来指定反序列化时使用的默认类型。visible(可选,默认false):属性定义了类型标识符是否会成为反序列化器的一部分,默认为false,也就是说Jackson会从json内容中删除类型标识再传递给JsonDeserializer。@JsonSubTypes
作用于类/接口,用来列出给定类/接口的子类。一般配合@JsonTypeInfo
使用
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "channel")@JsonSubTypes({ @JsonSubTypes.Type(value = PushMessageRequest.class, name = "PUSH"), @JsonSubTypes.Type(value = EmailMessageRequest.class, name = "EMAIL")})
JsonSubTypes
的值是一个@JsonSubTypes.Type[]
数组,参数value
表示类型,参数name
表示@JsonTypeInfo
注解中code>property属性的值,对比以上代码即:channel = "PUSH"或channel = "EMAIL"。name
为可选值,不指定时需在子类提供JsonTypeName
注解并指定value
属性。
实战
改造上面提供的MessageReuqest
// include默认为PROPERTY,这里可以不加@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "channel")@JsonSubTypes({ @JsonSubTypes.Type(value = PushMessageRequest.class, name = "PUSH"), @JsonSubTypes.Type(value = EmailMessageRequest.class, name = "EMAIL")})public class MessageRequest implements Serializable { protected MessageChannel channel; private MessageRequest(){} protected MessageRequest(MessageChannel channel){ this.channel = channel; } public MessageChannel getChannel() { return this.channel; }}
此时通过postman请求发现入参类型有了变化
include属性使用默认的PROPERTY时发现序列化之后的json会多出来一个属性,属性名对应的就是@JsonTypeInfo
的property
的值。虽然不影响使用,但是我看着很不舒服。基于我这种情况可以使用include=EXISTING_PROPERTY
。
总结
到此这篇关于Jackson多态序列化的文章就介绍到这了,更多相关Jackson多态序列化内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。