【java基础】根据泛型动态构造jackson的TypeReference(json反序列化为带泛型的类的对象)
根据泛型动态构造jackson的TypeReference
- 引出问题
- 使用TypeReference反序列化的例子
- 根据泛型动态构造TypeReference
- 带泛型的类如何表示?
- 完成HttpClient的实现
引出问题
- 将json字符串反序列化为带泛型的类的对象怎么操作?
- 怎么根据
TypeReference<List<People>>对象动态构造TypeReference<Result<List<People>>>对象
使用TypeReference反序列化的例子
有以下类定义:
class Result<T> {private long code;private T data;
}class People {private String name;
}
实例化以下对象:
Result<List<People>> result = new Result<>();
List<People> peopleList = new ArrayList<>();
People xiaoHong = new People("小红");
People xiaoMing = new People("小明");
peopleList.add(xiaoHong);
peopleList.add(xiaoMing);
result.setData(peopleList);
其对应的JSON字符串为:
{"code":0,"data":[{"name":"小红"},{"name":"小明"}]}
下面使用jackson的TypeReference来反序列化字符串为以上的对象:
String jsonStr = "{\"code\":0,\"data\":[{\"name\":\"小红\"},{\"name\":\"小明\"}]}";
TypeReference<Result<List<People>>> typeReference = new TypeReference<Result<List<People>>>() {};
ObjectMapper objectMapper = new ObjectMapper();
Result<List<People>> listResult = objectMapper.readValue(jsonStr, typeReference);
当我们构造http客户端的时候,有时候不想让用户看到类似Result<List<People>>这样的返回,只想给用户List<People>这样的数据,那怎么动态构造TypeReference呢?
根据泛型动态构造TypeReference
假设我们提供了一个http客户端工具,它的定义是这样的。
class HttpClient {public <T> T get(String url, Map<String,Object> params, TypeReference<T> typeR) {//获取jsonStr, 假设这里获取到的是:{"code":0,"data":[{"name":"小红"},{"name":"小明"}]}String jsonStr = execute(url, params);//todo 解析为枚举类型,下面会讲解如何实现}
}
假设我们这样调用HttpClient:
HttpClient client = new HttpClient();
//注意这里的TypeReference的泛型
List<People> result = client.get("http://xxxx", params, new TypeReference<List<People>>());
额额额???为啥不是TypeReference<Result<List<People>>> ???
这就是我们要达到的目的,即用户不关注外层包裹的Result,只需要指定实际想要的类型即可。下面我们来看下如何实现。
带泛型的类如何表示?
首先我们实现一个ParameterizedType的子类,至于这个类的作用请往下看:
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;public class ParameterizedTypeImpl implements ParameterizedType, Serializable {private final Type[] actualTypeArguments;private final Type ownerType;private final Type rawType;public ParameterizedTypeImpl(Type[] actualTypeArguments, Type ownerType, Type rawType) {this.actualTypeArguments = actualTypeArguments;this.ownerType = ownerType;this.rawType = rawType;}@Overridepublic Type[] getActualTypeArguments() {return this.actualTypeArguments;}@Overridepublic Type getRawType() {return this.rawType;}@Overridepublic Type getOwnerType() {return this.ownerType;}
}
我们来解释一下这个类,先看一下这个类的继承链:
ParameterizedTypeImpl implements ParameterizedType extends Type
- Type接口的语义是指:类型,标识java里的所有类。(注意:Class类也是Type的实现类,下面会用到)
- ParameterizedType接口的语义是:带泛型的类。
在java9之前jdk是包含了ParameterizedTypeImpl的实现的,但在jdk9及以后就没了,所以保险起见我们自己需要实现一下。
我们再看一下TypeReference的定义:
public abstract class TypeReference<T> implements Comparable<TypeReference<T>> {protected final Type _type;protected TypeReference() {Type superClass = this.getClass().getGenericSuperclass();if (superClass instanceof Class) {throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information");} else {this._type = ((ParameterizedType)superClass).getActualTypeArguments()[0];}}public Type getType() {return this._type;}public int compareTo(TypeReference<T> o) {return 0;}
}
这里的_type成员变量即ParameterizedTypeImpl类型。
我们继续看ParameterizedTypeImpl几个成员变量的意思:(此处以:new TypeReference<Result<List<People>>>为例)
- rawType
此处的rowType=Result.class,即原始的类是什么 - actualTypeArguments
此处的actualTypeArguments=new Type[]{List<People>.class},为什么是数组类型,是因为泛型里面可以放多个类型,我可以这么放:Result<List<People>,Set<People>>,那么这里的actualTypeArguments=new Type[]{List<People>.class,Set<People.class>},因为是一个Type数组,而每个Type又是一个ParameterizedType,所以可以向下继续查看(嵌套)。 - ownerType
所谓的ownerType只在嵌套类中会出现,其他情况为空。举个例子:I<T>.S<E>,则S<E>的ownerType=I<T>
完成HttpClient的实现
class HttpClient {public <T> T get(String url, Map<String,Object> params, TypeReference<T> typeR) {//获取jsonStr, 假设这里获取到的是:{"code":0,"data":[{"name":"小红"},{"name":"小明"}]}String jsonStr = execute(url, params);ObjectMapper objectMapper = new ObjectMapper();//在此处偷梁换柱TypeReference<Result<T>> resultType = new TypeReference<Result<T>>>() {@Overridepublic Type getType() {//在外层再包一层Result,就是所谓的动态构造,是不是很简单!!!return new ParameterizedTypeImpl(new Type[]{typeR.getType()},null, Result.class);}};Result<T> listResult = objectMapper.readValue(jsonStr, resultType);//此处省略了一下异常判断,不可直接这么使用return listResult.getData();}
}
然后我们就可以这么调用了:
HttpClient client = new HttpClient();
//注意这里的TypeReference的泛型
List<People> result = client.get("http://xxxx", params, new TypeReference<List<People>>());
OK,完结!
相关文章:
【java基础】根据泛型动态构造jackson的TypeReference(json反序列化为带泛型的类的对象)
根据泛型动态构造jackson的TypeReference引出问题使用TypeReference反序列化的例子根据泛型动态构造TypeReference带泛型的类如何表示?完成HttpClient的实现引出问题 将json字符串反序列化为带泛型的类的对象怎么操作?怎么根据TypeReference<List<…...
为什么VMware会给我多创建了两个网络呢?Windows和Linux为什么可以彼此ping的通呢
为什么VMware会给我多创建了两个网络呢?Windows和Linux为什么可以彼此ping的通呢 文章目录为什么VMware会给我多创建了两个网络呢?Windows和Linux为什么可以彼此ping的通呢桥接模式ANT模式(VMnet8)仅主机模式(VMnet1&a…...
服务器带宽承载多少人同时访问计算方法-浏览器中查看当前网页所有资源数据大小-客服系统高并发承载人数【唯一客服】...
浏览器中怎么查看当前网页所有资源的数据大小 在开发者工具的“网络”选项卡中,可以看到所有请求和响应的详细信息,包括每个资源的大小。如果需要查看网页所有资源的总大小,可以按照以下步骤操作: 打开要查看的网页。打开开发者工…...
给新手----编译VSOMEIP保姆级别教程
前言:当你学习了SOMEIP理论基础后,一定很希望上手实操一波吧,本文档以SOMEIP协议里比较成熟的VSOMEIP开源框架为例,带你从0到1实现开源框架的下载到上手,坐稳啦,开车!!!&…...
MarkDown设置上下标
上标:$a^{2-5}$ 下标:$a_{n-1}$显示:结果 上标:a2−5a^{2-5}a2−5 下标:an−1a_{n-1}an−1 如果上下标中需要多个显示,需要用{}括起来,否则就像下面一样 上标:$a^2-5$ 下标&…...
Python批量爬取游戏卡牌信息
文章目录前言一、需求二、分析三、处理四、运行结果前言 本系列文章来源于真实的需求本系列文章你来提我来做本系列文章仅供学习参考阅读人群:有Python基础、Scrapy框架基础 一、需求 全站爬取游戏卡牌信息 二、分析 查看网页源代码,图片资源是否存在…...
什么是PCB走线的3W原则
在设计PCB的时候我们会经常说到3W原则, 它指的是两个PCB走线它们的中心间距不小于3倍线宽,这个W就是PCB走线的宽度。这样做的目的主要是为了减小走线1和走线2之间的串扰,一般对于时钟信号,复位信号等一些关键信号需要遵循3W原则。…...
计算机网络面试总结
计算机网络 1.计算机网络 2.计算机网络拓扑结构 3.计算机网络覆盖 4.时延 5.交换技术 6.单工、半双工、全双工 7.OSI模型 8.TCP/IP模型 9.物理层有哪些设备 10.数据链路层介质访问控制 11.数据链路层有哪些设备 12.数据链路层流量控制 13.数据链路层的三个基本问题和解决方法 1…...
VsCode SSH远程连接服务器【内网穿透公网连接】
文章目录1.前言2.VS code的安装和设置2.1 VS code的下载安装2.2 OpenSSH的启用2.3 为VS code配置ssh2.4 局域网内测试VS code的ssh连接2.5 Cpolar下载安装3.Cpolar端口设置3.1 Cpolar云端设置3.2 Cpolar本地设置4.公网访问测试5.结语1.前言 记得笔者小时候看电视,看…...
十八、动画与canvas
1.RequestAnimationFrame 早期定时动画 setTimeout和setInterval不能保证时间精度,第二个参数只能保证何时将代码添加到浏览器的任务队列 requestAnimationFrame(cb)的cb在浏览器重绘屏幕前调用 function updateProgress(){const div document.getElementById(d…...
自动化测试学习-Day4-selenium的安装和8种定位方法
哈喽,大家好! 本人21年毕业,软件工程专业,毕业后一直从事金融行业的软件测试。 希望大家一起见证一名卑微测试的成长之路。 目录 一、环境准备 1.浏览器下载 2.浏览器驱动下载 3.下载selenium 二、Selenium定位元素的8种方法…...
【Kubernetes】第二十五篇 - 布署 nodejs 后端项目(下)
一,前言 上一篇,介绍了部署后端项目之前,需要的准备的相关配置信息; 本篇,创建 Deployment、Service 完成后端项目布署; 二,解决 jenkins 安全问题 构建 docker 镜像之后,登录 do…...
贪心算法之区间问题总结
一、跳跃游戏跳跃游戏类的问题,不关心每一步怎么跳,只需要关心最大覆盖范围这里注意i是在当前最大可覆盖范围内遍历,如{2,1,0,1},就是在0~2范围内遍历,千万不能0~numsSize-1范围内遍历!!&#x…...
无线WiFi安全渗透与攻防(七)之WIFI07-WEP-wifite自动化渗透WEP加密
WIFI07-WEP-wifite自动化渗透WEP加密 1.wifite介绍 wifite是一款自动化wep、wpa以及wps破解工具,不支持windows和osx。wifite的特点是可以同时攻击多个采用wep和wpa加密的网络。wifite只需简单的配置即可自动化运行,期间无需人工干预。 目前支持任何li…...
震撼,支持多模态模型的ChatGPT 4.0发布了
最近几个月,互联网和科技圈几乎ChatGPT刷屏了,各种关于ChatGPT的概念和应用的帖子也是围绕在周围。当去年年底ChatGPT发布的那几天,ChatGPT确实震撼到了所有人,原来AI还可以这么玩,并且对国内的那些所谓的人工智能公司…...
IDEA常用插件列表
一 背景 IDEA常用插件列表,用来提供工作效率。你都安装了吗 IntelliJ IDEA 默认安装并提供了非常多的工具,比如 Maven Integration、Markdown support、SSH Remote Run 等。其中有很多好用,但是不为人知的工具。 二 插件列表 阿里代码规约…...
比df更好用的命令!
大家好,我是良许。 对于分析磁盘使用情况,有两个非常好用的命令:du 和 df 。简单来说,这两个命令的作用是这样的: du 命令:它是英文单词 disk usage 的简写,主要用于查看文件与目录占用多少磁…...
【Git使用学习】记录学习过程(1)
安装就省略了,安装结果如下。 Git Bash:这是一个模拟Linux环境的命令行工具,可以使用Git的所有功能。Git GUI:这是一个图形化界面的工具,可以方便地执行Git的常用操作。Git CMD:这是一个Windows命令行工具&…...
K_A18_001 基于STM32等单片机采集MQ2传感参数串口与OLED0.96双显示
K_A18_001 基于STM32等单片机采集MQ2传感参数串口与OLED0.96双显示一、资源说明二、基本参数参数引脚说明三、驱动说明IIC地址/采集通道选择/时序对应程序:四、部分代码说明1、接线引脚定义1.1、STC89C52RCMQ2传感参模块1.2、STM32F103C8T6MQ2传感参模块五、基础知识学习与相关…...
【云原生·Docker】常用命令
目录 🍁1、管理命令 🍁2、帮助命令 🍁3、镜像命令 🍁4、容器命令 🍂4.1.查看容器 🍂4.2.创建容器 🍂4.3.删除容器 🍂4.4.拷贝文件 🍂4.5.查看容器IP 🍁5、部署…...
Hi-C数据分析进阶:如何用dcHiC精准识别癌症样本中的区室转换事件?
Hi-C技术解密:从染色质区室动态到癌症表观遗传调控 染色质三维结构研究已成为癌症表观遗传学的前沿领域。随着Hi-C技术的普及,科学家们能够以前所未有的分辨率观察基因组在细胞核内的空间组织形式。本文将深入探讨染色质区室(A/B compartment…...
从理论到代码:手把手实现Newmark-Beta方法的结构动力学模拟
从理论到代码:手把手实现Newmark-Beta方法的结构动力学模拟 结构动力学模拟是现代工程设计与分析中不可或缺的工具,从桥梁抗震到航天器振动分析,都需要精确预测结构在动态载荷下的响应。而Newmark-Beta方法作为这一领域的经典算法,…...
Clover Bootloader虚拟化环境部署终极指南:QEMU、KVM、Xen全平台支持
Clover Bootloader虚拟化环境部署终极指南:QEMU、KVM、Xen全平台支持 【免费下载链接】CloverBootloader Bootloader for macOS, Windows and Linux in UEFI and in legacy mode 项目地址: https://gitcode.com/gh_mirrors/cl/CloverBootloader Clover Bootl…...
突破微信设备限制:WeChatPad如何实现免Root双设备同时在线
突破微信设备限制:WeChatPad如何实现免Root双设备同时在线 【免费下载链接】WeChatPad 强制使用微信平板模式 项目地址: https://gitcode.com/gh_mirrors/we/WeChatPad 你是否曾因微信只能单设备登录而错失重要消息?是否渴望在手机和平板上同时接…...
探索Ryujinx:Nintendo Switch模拟器全解析
探索Ryujinx:Nintendo Switch模拟器全解析 【免费下载链接】Ryujinx 用 C# 编写的实验性 Nintendo Switch 模拟器 项目地址: https://gitcode.com/GitHub_Trending/ry/Ryujinx 在游戏技术不断发展的今天,模拟器技术为玩家提供了跨平台体验游戏的可…...
【经验贴】考过CDA数据分析师二级,从互联网公司转行大型国企下的数据分析统计部门经验
一、个人经历 2015年进了一家互联网公司,经过这几年的快速发展,到2020年的时候,我已经混到总监了。产品、运营、销售支持,这三方面的活都干过。也算是赶上了这波红利的尾巴,这些年也挣了点钱。 2020年后,…...
TouchGal:一站式Galgame社区解决方案终极指南
TouchGal:一站式Galgame社区解决方案终极指南 【免费下载链接】kun-touchgal-next TouchGAL是立足于分享快乐的一站式Galgame文化社区, 为Gal爱好者提供一片净土! 项目地址: https://gitcode.com/gh_mirrors/ku/kun-touchgal-next 还在为寻找Galgame资源而四…...
如何利用系统提示词革新开源项目的AI功能实现
如何利用系统提示词革新开源项目的AI功能实现 【免费下载链接】system_prompts_leaks 项目地址: https://gitcode.com/GitHub_Trending/sy/system_prompts_leaks 在人工智能技术快速发展的今天,系统提示词已成为解锁AI潜能的关键钥匙。对于开源项目而言&…...
Unity开发HoloLens应用:从打包到安装的完整避坑指南(2024最新版)
Unity开发HoloLens应用:从打包到安装的完整避坑指南(2024最新版) 如果你正在尝试将Unity项目部署到HoloLens设备上,可能会遇到各种意想不到的问题。作为一位经历过无数次打包、部署、调试循环的开发者,我想分享一些实战…...
跨平台开发终极对决:uniapp、uniapp-X、React Native 与 Flutter 全面解析
作者:前端组件开发 发布日期:2026年2月20日 关键词:跨平台开发、uniapp、uniapp-X、React Native、Flutter、前端框架选型 在移动应用开发日益多元化的今天,如何在保证用户体验的同时提升开发效率,成为每个团队必须面对…...
