fastjson 泛型转换问题(详解)

系列文章目录

附属文章一:fastjson TypeReference 泛型类型(详解)


文章目录

  • 系列文章目录
  • 前言
  • 一、代码演示
    • 1. 不存在泛型转换
    • 2. 存在泛型转换
    • 3. 存在泛型集合转换
  • 二、原因分析
  • 三、解决方案
    • 1. 方案1:重新执行泛型的 json 转换
    • 2. 方案2:使用 TypeReference 指定泛型类型


前言

本文讲解使用 fastjson 进行 json 转换泛型 T、泛型集合 R<List>、或者子类中的泛型、或者多层泛型,存在的 json 转换异常报错问题,以及解决方案。


一、代码演示

data 实际对象类型:

@Data
public class SysUser {String userId;String userName;
}

1. 不存在泛型转换

响应类:

@Data
public class R {Integer code;String msg;SysUser data;
}

测试类:


@Slf4j
public class Test {public static void main(String[] args) {String jsonStr = "{\"code\":0,\"msg\":\"操作成功\",\"data\":{\"userId\":\"1001\",\"userName\":\"小白\"}}";R rSysUser = JSONObject.parseObject(jsonStr, R.class);SysUser sysUser = rSysUser.getData();log.info("sysUser={}", sysUser.toString());}
}

执行上述代码,结果如下:

在这里插入图片描述

通过断点调试可以看到 JSONObject.parseObject(jsonStr, R.class) 转换后的对象中的子对象的实际类型为 SysUser,数据为等值的形式。

2. 存在泛型转换

泛型响应类:

@Data
public class R<T> {Integer code;String msg;T data;
}

泛型测试类:


@Slf4j
public class Test {public static void main(String[] args) {String jsonStr = "{\"code\":0,\"msg\":\"操作成功\",\"data\":{\"userId\":\"1001\",\"userName\":\"小白\"}}";R<SysUser> rSysUser = JSONObject.parseObject(jsonStr, R.class);SysUser sysUser = rSysUser.getData();log.info("sysUser={}", sysUser.toString());}
}

执行上述代码,结果如下:

在这里插入图片描述

通过断点调试可以看到 JSONObject.parseObject(jsonStr, R.class) 转换后的对象中的子泛型对象的实际类型为 JSONObject,数据为 key-value 的形式。

此时往下执行,进行 JSONObject 和 SysUser 对象的直接赋值,就会抛出异常:

在这里插入图片描述

3. 存在泛型集合转换

泛型集合测试类:


@Slf4j
public class Test {public static void main(String[] args) {String jsonStr = "{\"code\":0,\"msg\":\"操作成功\",\"data\":[{\"userId\":\"1001\",\"userName\":\"小白\"}]}";R<List<SysUser>> rSysUser = JSONObject.parseObject(jsonStr, R.class);List<SysUser> sysUserList = rSysUser.getData();log.info("sysUserList={}", sysUserList.toString());SysUser sysUser = sysUserList.get(0);log.info("sysUser={}", sysUser.toString());}
}

执行上述代码,结果如下:
在这里插入图片描述
通过断点调试可以看到 JSONObject.parseObject(jsonStr, R.class) 转换后的对象中的泛型集合对象的实际类型为 JSONObject,数据为 key-value 的形式。

此时往下执行,进行 JSONObject 和 SysUser 对象的直接赋值,就会抛出异常:
在这里插入图片描述

扩展:

当然,泛型 T、泛型集合 R<List>、或者子类中的泛型、或者多层泛型,都存在同样的问题。本文不再演示。

二、原因分析

因为当 json 转换的对象是泛型时,我们无法获取到实际的类,无法获取到类的变量,也无法获取到类变量的 get、set 方法,所以我们无法将这个 json 数据转换到某一个实际的类对象中存储,所以 com.alibaba.fastjson 会临时转换为 JSONObject 对象,以 key-value 形式存储。

这样就存在一个问题,当我们将该泛型对象赋值转换为实际的类对象时,就会因类型不匹配而抛出异常。

三、解决方案

1. 方案1:重新执行泛型的 json 转换

将泛型转换为 json 字符串后,重新进行类对象转换。

泛型转换:

R<SysUser> rSysUser = JSONObject.parseObject(jsonStr, R.class);
SysUser sysUser = JSONObject.parseObject(JSONObject.toJSONString(rSysUser.getData()), SysUser.class);

泛型集合转换:

R<List<SysUser>> rSysUser = JSONObject.parseObject(jsonStr, R.class);
List<SysUser> sysUserList = JSONObject.parseArray(JSONObject.toJSONString(rSysUser.getData()), SysUser.class);

2. 方案2:使用 TypeReference 指定泛型类型

使用 fastjson 的 TypeReference 来指定泛型类型。

在指定了 json 转换中泛型的实际类型后,就能获取到实际的类,获取到类的变量,获取到类变量的 get、set 方法,从而将泛型的 json 转换成实际的类对象。

本文不过多讲解 TypeReference 类,详细了解请转 《fastjson TypeReference 泛型类型(详解)》https://editor.csdn.net/md/?articleId=139363645

泛型转换:

R<SysUser> rSysUser = JSONObject.parseObject(jsonStr, new TypeReference<R<SysUser>>(){});
SysUser sysUser = rSysUser.getData();

泛型集合转换:

R<List<SysUser>> rSysUser = JSONObject.parseObject(jsonStr, new TypeReference<R<List<SysUser>>>(){});
List<SysUser> sysUserList = rSysUser.getData();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/340656.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

23种模式之一— — — —适配器模式的详细介绍与讲解

适配器介绍与讲解 一、概念二、适配器模式结构适配器分类核心思想核心角色模式的UML类图应用场景模式优点模式缺点 实例演示图示代码演示运行结果 一、概念 适配器模式&#xff08;别名&#xff1a;包装器&#xff09; 是一种结构型设计模式 将一个类的接口转换成客户希望的另…

每日一练:利用多态思想和ArrayList集合,编写一个模拟KTV点歌系统的程序。【多态思想和ArrayList集合的综合应用】

目录 一、设计程序使用ArrayList集合&#xff0c;编写一个模拟KTV点歌系统的程序。参考代码歌曲类歌单类KTV类测试类运行效果 总结 最后 一、设计程序 使用ArrayList集合&#xff0c;编写一个模拟KTV点歌系统的程序。 要求&#xff1a; 输入0代表添加歌曲输入1代表将所选歌曲…

STM32高级控制定时器之输入捕获模式

目录 概述 1 输入捕获模式 1.1 原理介绍 1.2 实现步骤 1.3 发生输入捕获流程 2 使用STM32Cube配置工程 2.1 软件环境 2.2 配置参数 2.3 生成项目文件 3 功能实现 3.1 PWM调制占空比函数 3.2 应用函数库 4 测试 4.1 功能框图 4.2 运行结果 源代码下载地址&#xf…

MySQL 存储过程(一)

本篇主要介绍MySQL存储过程的相关内容 目录 一、什么是存储过程&#xff1f; 二、基本语法 创建存储过程 调用存储过程 查看存储过程 删除存储过程 三、变量 系统变量 用户自定义变量 局部变量 四、存储过程的参数 in out inout 一、什么是存储过程&#xff1f…

9 个步骤内快速完成 SEO 审核

SEO审计对于提高网站在搜索引擎结果中的性能和可见性至关重要。这种系统评估涉及仔细检查各种元素&#xff0c;从关键字和页面优化到网站结构和页面速度等技术方面。在本指南中&#xff0c;我们将概述执行全面 SEO 检查器的 12 个基本步骤&#xff0c;帮助您确定优势、劣势和改…

基于小波区间相关的信号降噪方法(MATLAB 2021B)

在我们处理信号过程中最重要的任务就是找到信号隐藏的规律和信号的特征。常用的傅里叶分析法只能用于在时间域或者频率域上分析信号&#xff0c;而通常的数据会在时间域和频率域均有特征。而小波分析是继傅里叶分析之后的一大突破性创新&#xff0c;也是近年来在学术界非常热门…

小熊家务帮day5-day7 客户管理模块1 (小程序认证,手机验证码认证,账号密码认证,修改密码,找回密码等)

客户管理模块 1.认证模块1.1 认证方式介绍1.1.1 小程序认证1.1.2 手机验证码登录1.1.3 账号密码认证 1.2 小程序认证1.2.1 小程序申请1.2.2 创建客户后端工程jzo2o-customer1.2.3 开发部署前端1.2.4 小程序认证流程1.2.4.1 customer小程序认证接口设计Controller层Service层调用…

使用import语句导入模块

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 创建模块后&#xff0c;就可以在其他程序中使用该模块了。要使用模块需要先以模块的形式加载模块中的代码&#xff0c;这可以使用import语句实现。im…

react、vue动态form表单

需求在日常开发中反复写form 是一种低效的开发效率&#xff0c;布局而且还不同这就需要我们对其封装 为了简单明了看懂代码&#xff0c;我这里没有组件&#xff0c;都放在一起&#xff0c;简单抽离相信作为大佬的你&#xff0c;可以自己完成&#xff0c; 一、首先我们做动态f…

外包小菜鸡花了几个w报的课立志进大厂

不知不觉已经毕业了好几年&#xff0c;但是感觉还是自己的年龄增长了而已&#xff0c;对应的技术却没学到&#xff0c;最后一咬牙报了图灵的架构VIP班&#xff0c;不得不说&#xff0c;诸葛老师讲的是真的好呀&#xff0c;大家可以看看他的公开课&#xff0c;希望学完下面这些视…

JVMの内存泄漏内存溢出案例分析

1、内存溢出 内存溢出指的是程序在申请内存时&#xff0c;没有足够的内存可供分配&#xff0c;导致无法满足程序的内存需求&#xff0c;常见的内存溢出情况包括堆内存溢出&#xff08;Heap Overflow&#xff09;和栈溢出&#xff08;Stack Overflow&#xff09;&#xff1a; …

《数字图像处理-OpenCV/Python》第15章:图像分割

《数字图像处理-OpenCV/Python》第15章&#xff1a;图像分割 本书京东 优惠购书链接 https://item.jd.com/14098452.html 本书CSDN 独家连载专栏 https://blog.csdn.net/youcans/category_12418787.html 第15章&#xff1a;图像分割 图像分割是由图像处理到图像分析的关键步骤…

spark的简单学习二

一 spark sql基础 1.1 Dataframe 1.介绍&#xff1a; DataFrame也是一个分布式数据容器。然而DataFrame更像传统数据库的二维表 格&#xff0c;除了数据以外&#xff0c;还掌握数据的结构信息&#xff0c;即schema。同时&#xff0c;与Hive类似&#xff0c;DataFrame也支 持…

STM32_HAL_I2C_串行接口

电气特性 I2C&#xff08;Inter-Integrated Circuit&#xff09;是一种由飞利浦公司&#xff08;现恩智浦半导体&#xff09;开发的串行通信协议&#xff0c;用于连接低速外围设备。I2C总线只需要两根线&#xff08;SDA&#xff1a;串行数据线&#xff0c;SCL&#xff1a;串行…

免费生物蛋白质的类chatgpt工具助手copilot:小分子、蛋白的折叠、对接等

参考: https://310.ai/copilot 可以通过自然语言对话形式实现小分子、蛋白质的相关处理:生成序列、折叠等 应该是agent技术调用不同工具实现 从UniProt数据库中搜索和加载蛋白质。使用ESM Fold方法折叠蛋白质。使用310.ai基础模型设计新蛋白质。使用TM-Align方法比较蛋白质…

【Spring Cloud】微服务链路跟踪Sleuth

目录 为什么要使用微服务链路跟踪微服务的现状多服务协同工作复杂的调用链条容易出错 微服务链路跟踪需要实现的需求实现监控决策避免技术债务快速定位故障 微服务链路跟踪的技术要求低消耗应用透明延展性可控采样率可视化 Spring Cloud Sleuth简介Spring Cloud Sleuth的4个特点…

Shell脚本快速入门

为什么要学shell&#xff1f;能做什么&#xff1f; 答&#xff1a;CI/CD 持续集成&#xff0c;自动化部署作业方式&#xff0c;需要将一系列linux命令程序化&#xff0c;shell 就能做到&#xff0c;提高运维人员的工作效率。 指定解析器&#xff1a; (1) shell解析器 #…

Linux网络-自定义协议、序列化和反序列化、网络计算服务器的实现和Windows端客户端

文章目录 前言一、自定义协议传结构体对象 序列化和反序列化什么是序列化&#xff1f;反序列化 二、计算器服务端&#xff08;线程池版本&#xff09;1.main.cc2.Socket.hpp3.protocol.hpp4.Calculator.hpp5.serverCal.hpp6.threadPool.hpp7.Task.hpp8. log.hpp 客户端Windows客…

小白级教程—安装Ubuntu 20.04 LTS服务器

下载 本教程将使用20.04版进行教学 由于官方速度可能有点慢&#xff0c;可以下方的使用清华镜像下载 https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/ 点击20.24版本 选择 ubuntu-20.04.6-live-server-amd64.iso 新建虚拟机 下载好后 我们使用 VMware 打开它 这里选…

一篇文章讲透排序算法之归并排序

0.前言 本篇文章将详细解释归并排序的原理&#xff0c;以及递归和非递归的代码原理。 一.概念 归并排序是建立在归并操作上的一种有效的排序算法&#xff0c;该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使…