文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Jackson多态序列化图文详解

2024-04-02 19:55

关注

场景

做一个消息中心,专门负责发送消息。消息分为几种渠道,包括手机通知(Push)、短信(SMS)、邮件(Email),Websocket等渠道。

我定义了一个基类MessageRequest用来接收请求参数,代码如下:

public class MessageRequest implements Serializable {
  protected MessageChannel channel;
  private MessageRequest(){}
  protected MessageRequest(MessageChannel channel){
    this.channel = channel;
  }
  
  public MessageChannel getChannel() {
    return this.channel;
  }
}

MessageRequest中有个属性channel是枚举MessageChannel,该枚举列举所有渠道,代码如下:

public enum MessageChanne {
  PUSH,
  EMAIL,
  WEBSOCKET,
  SMS,
  ;
  
  MessageChannel() {}
}

MessageRequest有各种渠道的子类实现,以Push为例:

public class PushMessageReuqest extends MessageRequest {
  public PushMessageRequest() {
    super(MessageChannel.PUSH);
  }
  
  private String title;
  // 省略其他字段以及getter、setter方法
  ...
}

我在接口入参使用MessageRequest接收:

public class MessageController {
  @PostMapping("/sendMessage")
  public R<Object> sendMessage(MessageRequest request) {
    System.out.println(request);
  }
}

使用postman发送push请求之后发现后端收到的类型还是基类,并且title字段丢失。

这与我预想的不符,因为客户端知道渠道,构建对应的渠道消息体给我就好了啊!为什么类型被擦除了呢?我的想法就是发送push请求啊。。。。。后来才知道序列化之后在反序列化的时候不知道给你反序列化成什么类型,序列化工具也没有聪明到能根据你的channel属性就知道是什么类型,但是我又想这样做。那么怎么办呢????

Jackson多态类型序列化/反序列化

经过查询资料以及咨询了一下领导,发现了@JsonTypeInfo@JsonSubTypes两个注解。

@JsonTypeInfo作用于类/接口,被用来开启多态类型处理,它有一些属性:

@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注解中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会多出来一个属性,属性名对应的就是@JsonTypeInfoproperty的值。虽然不影响使用,但是我看着很不舒服。基于我这种情况可以使用include=EXISTING_PROPERTY

总结

到此这篇关于Jackson多态序列化的文章就介绍到这了,更多相关Jackson多态序列化内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯