fastjson 泛型转换问题(详解)

news2024/11/17 21:20:49

系列文章目录

附属文章一: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.coloradmin.cn/o/1799793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java使用GDAL来解析KMZ及KML实战

目录 前言 一、在GQIS中浏览数据 1、关于空间参考 2、属性表格 二、GDAL的相关驱动及解析实战 1、GDAL中的KMZ驱动 2、GDAL实际解析 三、数据解析成果 1、KML解析结果 2、KMZ文件入库 四、总结 前言 在前面的博客中讲过纯Java实现Google地图的KMZ和KML文件的解析&…

java第二十一课 —— 快捷键,包,访问修饰符

IDEA 快捷键 删除行&#xff1a;Ctrl Y复制行&#xff1a;Ctrl D补全代码&#xff1a;Alt /添加取消注释&#xff1a;Ctrl /导入该行需要的类&#xff1a;Alt Enter快速格式化代码&#xff1a;Ctrl Shift L快速运行程序&#xff1a;Ctrl Shift F10生成构造器&#xf…

Python实现调用并执行Linux系统命令

&#x1f60e; 作者介绍&#xff1a;我是程序员洲洲&#xff0c;一个热爱写作的非著名程序员。CSDN全栈优质领域创作者、华为云博客社区云享专家、阿里云博客社区专家博主。 &#x1f913; 同时欢迎大家关注其他专栏&#xff0c;我将分享Web前后端开发、人工智能、机器学习、深…

Oracle数据库设计规范指南(Word原件)

方便业务功能实现、业务功能扩展&#xff1b;方便设计开发、增强系统的稳定性和可维护性&#xff1b;保证数据完整性和准确性&#xff1b;提高数据存储效率&#xff0c;在满足业务需求的前提下&#xff0c;使时间开销和空间开销达到优化平衡。资料获取&#xff1a;本文本个人名…

tmux工具使用鼠标滚动窗口及分屏命令

tmux工具使用鼠标滚动窗口及分屏命令 1. tmux source配置文件 长期生效2. 临时生效3. 实现分屏 1. tmux source配置文件 长期生效 vim ~/.tmux.conf echo "set -g mouse on" > ~/.tmux.conf tmux source-file ~/.tmux.conf2. 临时生效 1. 进入到tmux命令窗口 2.…

【echarts】如何制作,横坐标每个日期点如何对应一条竖线的图,以及 markline设置后不生效问题

图的样式如下&#xff1a; 在线演示 每一个日期&#xff0c;对应一条竖线展示。 echarts配置内容&#xff1a; 在线演示 option {xAxis: {type: category,data: [20240601, 20240602, 20240603, 20240604, 20240605, 20240606, 20240607] // X轴数据},yAxis: {type: valu…

【Postman接口测试】第四节.Postman接口测试项目实战(中)

文章目录 前言五、Postman断言 5.1 Postman断言介绍 5.2 响应状态码断言 5.3 包含指定字符串断言 5.4 JSON数据断言六、参数化 5.1 Postman参数化介绍 5.2 Postman参数化实现 5.3 针对项目登录接口参数化实现 总结 前言 五、Postman断言 5.1 Postman断言介…

m3u8视频怎么打开?教你三招!

m3u8 是一种文本文件格式&#xff0c;用于创建媒体播放列表&#xff0c;现在大部分的视频流媒体都是m3u8格式。当我们从网上下载下来m3u8文件的时候会发现&#xff0c;它本身不是一段视频&#xff0c;而是一个索引纯文本文件。想要正常打开播放m3u8视频其实也很简单&#xff0c…

javaWeb4 Maven

Maven-管理和构建java项目的工具 基于POM的概念 1.依赖管理&#xff1a;管理项目依赖的jar包 &#xff0c;避免版本冲突 2.统一项目结构&#xff1a;比如统一eclipse IDEA等开发工具 3.项目构建&#xff1a;标准跨平台的自动化项目构建方式。有标准构建流程&#xff0c;能快速…

jvm学习笔记(三) ----- 垃圾回收器

这里写目录标题 1.单线程/串行收集器2.多线程回收器-吞吐量优先3. 多线程回收器-响应时间优先4.G1收集器5.GC参数 链接: jvm学习笔记(一) ----- JAVA 内存 链接: jvm学习笔记(二) ----- 垃圾回收 JVM垃圾回收性能有以下两个主要的指标: 吞吐量 &#xff1a;工作时间&#xff08…

牛客小白月赛95

vp&#xff0c;为后面的比赛做准备 A.相遇 #include <iostream> #include <vector> #include <algorithm> #include <set> #include <unordered_map> #include <cstring> #include <cstdio> #include <string> #include <…

vue-el-steps 使用2[代码示例]

效果图 代码 element代码 <template> <div class"app-container"> <el-form :model"queryForm" size"small" :inline"true"> <el-form-item label"内容状态"> <el-button-group> <el-bu…

代码随想录算法训练营day31|455.分发饼干、376.摆动序列、53.最大子序和

分发饼干 455. 分发饼干 - 力扣&#xff08;LeetCode&#xff09; 贪心算法&#xff0c;让每个饼干给到能够满足的孩子&#xff0c;所以需要对饼干尺寸和孩子的满足值先进行排序&#xff0c;然后针对每一个饼干的尺寸&#xff0c;挑选恰好能够满足的孩子&#xff08;这里表述…

fps游戏如何快速定位矩阵

fps游戏如何快速定位矩阵 矩阵特点: 1、第一行第一列值的范围在**-1 ---- 1**之间&#xff0c;如果开镜之后值会变大。 2、第一行第三列的值始终为 0。 3、第一行第四列 的值比较大 &#xff0c; >300或者**<-300**。 根据这三个特点&#xff0c;定位矩阵已经足够了…

DevExpress winForm gridView 设置复选框并可多选

OptionsSelection.MultiSelect True OptionsSelection.MultiSelectMode CheckBoxRowSelect

LabVIEW电路板性能与稳定性测试系统

LabVIEW电路板性能与稳定性测试系统 概述&#xff1a; 开发基于LabVIEW的电路板性能与稳定性测试系统&#xff0c;通过集成多种测试仪器&#xff0c;实现对电路板的电气性能和长期稳定性的全面评估。系统涵盖了电压、电流、温度等多项参数的监测&#xff0c;并具备自动化测试…

Towards Graph Contrastive Learning: A Survey and Beyond

目录 Towards Graph Contrastive Learning- A Survey and Beyond摘要IntroductionPRELIMINARY符号说明GNN对比学习下游任务 GCL自监督学习增强策略基于规则随机扰动或mask子图采样图扩散 基于学习图结构学习图对抗训练图合理化 对比模式同尺度对比全局上下文局部 跨尺度对比局部…

android-JNI

1.2【静态库】的特点&#xff1a; &#xff08;.a&#xff09; ①静态库对函数库的链接是在编译期完成的。执行期间代码装载速度快。 ②使可执行文件变大&#xff0c;浪费空间和资源&#xff08;占空间&#xff09;。 ③对程序的更新、部署与发布不方便&#xff0c;需要全量更新…

G5 - Pix2Pix理论与实战

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目录 理论知识图像翻译CGANU-NetPix2Pix损失函数模型结构生成器差别器 模型效果总结与心得体会 理论知识 前面已经学习了GAN与CGAN&#xff0c;这节开始学习P…

Android Webview 详解

一 简介 一个基于webkit引擎、展现web页面的控件 Android 4.4前&#xff1a;Android Webview在低版本 & 高版本采用了不同的webkit版本的内核Android 4.4后&#xff1a;直接使用了Chrome内核 1.1 作用 在 Android 客户端上加载h5页面在本地 与 h5页面实现交互 & …