当前位置: 首页 > news >正文

redis序列化数据时,如何包含clsss类型信息?

通过配置 `com.fasterxml.jackson.databind.ObjectMapper` 的 `enableDefaultTyping` 方法,可以使序列化后的 JSON 包含类信息。

大家可能留意过,在redis里缓存的数据经常有下面两种形式。不难发现,这两者的区别就是后者包含了JavaObject类型信息。

  • {"levyName":"test","levyCode":1}
  • {"@class":"jstudy.jacksoncodec.JacksonObjectMapperTest$ChannelLevyDTO","levyName":"test","levyCode":1}


要让redis序列化时包含class类型,自然是对程序里定义的 com.fasterxml.jackson.databind.ObjectMapper实例进行设置。没错,我们使用它的 enableDefaultTyping(com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping, com.fasterxml.jackson.annotation.JsonTypeInfo.As) 方法。

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL, JsonTypeInfo.As.PROPERTY);

关于这个方法的第2个参数JsonTypeInfo.AsJsonTypeInfo是Jackson库里的一个注解,JsonTypeInfo.As枚举用于指定在 JSON 中包含类型信息的方式。 默认值是 JsonTypeInfo.As.PROPERTY

我们用上面代码中的 objectMapper 写个demo↓

ChannelLevyDTO channelLevyDTO = new ChannelLevyDTO1();
channelLevyDTO.levyCode=1;
channelLevyDTO.levyName="test";
String s = objectMapper.writeValueAsString(channelLevyDTO);

执行demo程序可以看到,s对应的json串是 {"@class":"jstudy.jacksoncodec.JacksonObjectMapperTest$ChannelLevyDTO","levyName":"test","levyCode":1}

JsonTypeInfo.As 枚举类型定义了以下几种类型信息包含方式:

  • WRAPPER_ARRAY:将类型信息包装在 JSON 数组中。
  • WRAPPER_OBJECT:将类型信息包装在 JSON 对象中。
  • PROPERTY:将类型信息作为属性添加到 JSON 中。
  • EXISTING_PROPERTY:将类型信息添加到现有的属性中。
  • EXTERNAL_PROPERTY:将类型信息作为外部属性引用。

上面demo使用的是As.PROPERTY。

使用As.WRAPPER_OBJECT则是:{"jstudy.jacksoncodec.JacksonObjectMapperTest$ChannelLevyDTO":{"levyName":"test","levyCode":1}}

使用As.WRAPPER_ARRAY 则是:["jstudy.jacksoncodec.JacksonObjectMapperTest$ChannelLevyDTO",{"levyName":"test","levyCode":1}]

补充一点,Jackson库ObjectMapper类弃用了enableDefaultTyping,取而代之的是 activateDefaultTyping 。

// /**/m3/com/fasterxml/jackson/core/jackson-databind/2.11.0/jackson-databind-2.11.0-sources.jar!/com/fasterxml/jackson/databind/ObjectMapper.java/*** @deprecated Since 2.10 use {@link #activateDefaultTyping(PolymorphicTypeValidator,DefaultTyping,JsonTypeInfo.As)} instead*/
@Deprecated
public ObjectMapper enableDefaultTyping(DefaultTyping applicability, JsonTypeInfo.As includeAs) {return activateDefaultTyping(getPolymorphicTypeValidator(), applicability, includeAs);
}public ObjectMapper activateDefaultTyping(PolymorphicTypeValidator ptv,DefaultTyping applicability, JsonTypeInfo.As includeAs) {...TypeResolverBuilder<?> typer = _constructDefaultTypeResolverBuilder(applicability, ptv);// we'll always use full class name, when using defaultingtyper = typer.init(JsonTypeInfo.Id.CLASS, null);typer = typer.inclusion(includeAs);return setDefaultTyping(typer);
}

相比较可见,activateDefaultTyping 方法多了一个参数 PolymorphicTypeValidator,是用于验证多态类型信息的验证器。

activateDefaultTyping 这个方法允许我们指定如何处理多态类型信息以及如何在序列化和反序列化过程中包含类型信息。

需要说明的是,在未指定包括类型信息时,序列化后是仅包含数据的json串{"levyName":"test","levyCode":1},我们可以将一个JavaObjectA对象反序列化为JavaObjectB对象(前提是JavaObjectB包含JavaObjectA的所有field)。

而一旦在指定了包含类型信息后,将严格按照model类型进行反序列化。也就是说,这种情况下,把JavaObjectA反序列为JavaObjectB,程序会抛出异常:Could not resolve type id '%s' as a subtype of %s,其中第1个%s表示序列化对象JavaObjectA,第2个%s表示要反序列化的目标类型JavaObjectB↓

com.fasterxml.jackson.databind.exc.InvalidTypeIdException: Could not resolve type id 'jstudy.jacksoncodec.JacksonObjectMapperTest$ChannelLevyDTO' as a subtype of [simple type, class jstudy.jacksoncodec.JacksonObjectMapperTest$ChannelLevyDTO1]: Not a subtype

相关文章:

  • 多线程计算π
  • 力扣9.25
  • 51单片机如何判断浮点数nan
  • QT 如何判断电脑已安装某个软件
  • 知识点复习4
  • 漫步者头戴式耳机好用吗?漫步者、西圣、万魔顶级机型测评对比
  • (23)mysql中mysqldump备份数据库
  • java SE -- 线程 asset
  • 基于yolov8的游戏人物自动锁定功能
  • 排序--堆排序【图文详解】
  • Vert.x 和 Spring Boot 是两种流行的 Java 框架的比较
  • Java AI 编程助手
  • 探索图像生成大模型Imagen:原理、比较与应用
  • Nginx的核心架构和设计原理
  • 大语言模型技术点总结
  • 深入了解以太坊
  • angular2开源库收集
  • flask接收请求并推入栈
  • Git学习与使用心得(1)—— 初始化
  • IDEA常用插件整理
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • Java面向对象及其三大特征
  • js ES6 求数组的交集,并集,还有差集
  • Linux中的硬链接与软链接
  • MySQL主从复制读写分离及奇怪的问题
  • Python语法速览与机器学习开发环境搭建
  • spring-boot List转Page
  • uni-app项目数字滚动
  • 不发不行!Netty集成文字图片聊天室外加TCP/IP软硬件通信
  • 从 Android Sample ApiDemos 中学习 android.animation API 的用法
  • 大数据与云计算学习:数据分析(二)
  • 服务器之间,相同帐号,实现免密钥登录
  • 深入浏览器事件循环的本质
  • ​secrets --- 生成管理密码的安全随机数​
  • # 数仓建模:如何构建主题宽表模型?
  • # 消息中间件 RocketMQ 高级功能和源码分析(七)
  • #1014 : Trie树
  • #Linux(Source Insight安装及工程建立)
  • #如何使用 Qt 5.6 在 Android 上启用 NFC
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (16)Reactor的测试——响应式Spring的道法术器
  • (160)时序收敛--->(10)时序收敛十
  • (2009.11版)《网络管理员考试 考前冲刺预测卷及考点解析》复习重点
  • (C语言版)链表(三)——实现双向链表创建、删除、插入、释放内存等简单操作...
  • (solr系列:一)使用tomcat部署solr服务
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (附源码)计算机毕业设计大学生兼职系统
  • (使用vite搭建vue3项目(vite + vue3 + vue router + pinia + element plus))
  • (转)AS3正则:元子符,元序列,标志,数量表达符
  • (转)GCC在C语言中内嵌汇编 asm __volatile__
  • (转)JVM内存分配 -Xms128m -Xmx512m -XX:PermSize=128m -XX:MaxPermSize=512m
  • (转)Mysql的优化设置
  • .form文件_SSM框架文件上传篇
  • .Net CoreRabbitMQ消息存储可靠机制