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

【java基础】根据泛型动态构造jackson的TypeReference(json反序列化为带泛型的类的对象)

根据泛型动态构造jackson的TypeReference

  • 引出问题
  • 使用TypeReference反序列化的例子
  • 根据泛型动态构造TypeReference
    • 带泛型的类如何表示?
    • 完成HttpClient的实现

引出问题

  1. 将json字符串反序列化为带泛型的类的对象怎么操作?
  2. 怎么根据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带泛型的类如何表示&#xff1f;完成HttpClient的实现引出问题 将json字符串反序列化为带泛型的类的对象怎么操作&#xff1f;怎么根据TypeReference<List<…...

为什么VMware会给我多创建了两个网络呢?Windows和Linux为什么可以彼此ping的通呢

为什么VMware会给我多创建了两个网络呢&#xff1f;Windows和Linux为什么可以彼此ping的通呢 文章目录为什么VMware会给我多创建了两个网络呢&#xff1f;Windows和Linux为什么可以彼此ping的通呢桥接模式ANT模式&#xff08;VMnet8&#xff09;仅主机模式&#xff08;VMnet1&a…...

服务器带宽承载多少人同时访问计算方法-浏览器中查看当前网页所有资源数据大小-客服系统高并发承载人数【唯一客服】...

浏览器中怎么查看当前网页所有资源的数据大小 在开发者工具的“网络”选项卡中&#xff0c;可以看到所有请求和响应的详细信息&#xff0c;包括每个资源的大小。如果需要查看网页所有资源的总大小&#xff0c;可以按照以下步骤操作&#xff1a; 打开要查看的网页。打开开发者工…...

给新手----编译VSOMEIP保姆级别教程

前言&#xff1a;当你学习了SOMEIP理论基础后&#xff0c;一定很希望上手实操一波吧&#xff0c;本文档以SOMEIP协议里比较成熟的VSOMEIP开源框架为例&#xff0c;带你从0到1实现开源框架的下载到上手&#xff0c;坐稳啦&#xff0c;开车&#xff01;&#xff01;&#xff01;&…...

MarkDown设置上下标

上标&#xff1a;$a^{2-5}$ 下标&#xff1a;$a_{n-1}$显示&#xff1a;结果 上标&#xff1a;a2−5a^{2-5}a2−5 下标&#xff1a;an−1a_{n-1}an−1​ 如果上下标中需要多个显示&#xff0c;需要用{}括起来&#xff0c;否则就像下面一样 上标&#xff1a;$a^2-5$ 下标&…...

Python批量爬取游戏卡牌信息

文章目录前言一、需求二、分析三、处理四、运行结果前言 本系列文章来源于真实的需求本系列文章你来提我来做本系列文章仅供学习参考阅读人群&#xff1a;有Python基础、Scrapy框架基础 一、需求 全站爬取游戏卡牌信息 二、分析 查看网页源代码&#xff0c;图片资源是否存在…...

什么是PCB走线的3W原则

在设计PCB的时候我们会经常说到3W原则&#xff0c; 它指的是两个PCB走线它们的中心间距不小于3倍线宽&#xff0c;这个W就是PCB走线的宽度。这样做的目的主要是为了减小走线1和走线2之间的串扰&#xff0c;一般对于时钟信号&#xff0c;复位信号等一些关键信号需要遵循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.前言 记得笔者小时候看电视&#xff0c;看…...

十八、动画与canvas

1.RequestAnimationFrame 早期定时动画 setTimeout和setInterval不能保证时间精度&#xff0c;第二个参数只能保证何时将代码添加到浏览器的任务队列 requestAnimationFrame(cb)的cb在浏览器重绘屏幕前调用 function updateProgress(){const div document.getElementById(d…...

自动化测试学习-Day4-selenium的安装和8种定位方法

哈喽&#xff0c;大家好&#xff01; 本人21年毕业&#xff0c;软件工程专业&#xff0c;毕业后一直从事金融行业的软件测试。 希望大家一起见证一名卑微测试的成长之路。 目录 一、环境准备 1.浏览器下载 2.浏览器驱动下载 3.下载selenium 二、Selenium定位元素的8种方法…...

【Kubernetes】第二十五篇 - 布署 nodejs 后端项目(下)

一&#xff0c;前言 上一篇&#xff0c;介绍了部署后端项目之前&#xff0c;需要的准备的相关配置信息&#xff1b; 本篇&#xff0c;创建 Deployment、Service 完成后端项目布署&#xff1b; 二&#xff0c;解决 jenkins 安全问题 构建 docker 镜像之后&#xff0c;登录 do…...

贪心算法之区间问题总结

一、跳跃游戏跳跃游戏类的问题&#xff0c;不关心每一步怎么跳&#xff0c;只需要关心最大覆盖范围这里注意i是在当前最大可覆盖范围内遍历&#xff0c;如{2,1,0,1}&#xff0c;就是在0~2范围内遍历&#xff0c;千万不能0~numsSize-1范围内遍历&#xff01;&#xff01;&#x…...

无线WiFi安全渗透与攻防(七)之WIFI07-WEP-wifite自动化渗透WEP加密

WIFI07-WEP-wifite自动化渗透WEP加密 1.wifite介绍 wifite是一款自动化wep、wpa以及wps破解工具&#xff0c;不支持windows和osx。wifite的特点是可以同时攻击多个采用wep和wpa加密的网络。wifite只需简单的配置即可自动化运行&#xff0c;期间无需人工干预。 目前支持任何li…...

震撼,支持多模态模型的ChatGPT 4.0发布了

最近几个月&#xff0c;互联网和科技圈几乎ChatGPT刷屏了&#xff0c;各种关于ChatGPT的概念和应用的帖子也是围绕在周围。当去年年底ChatGPT发布的那几天&#xff0c;ChatGPT确实震撼到了所有人&#xff0c;原来AI还可以这么玩&#xff0c;并且对国内的那些所谓的人工智能公司…...

IDEA常用插件列表

一 背景 IDEA常用插件列表&#xff0c;用来提供工作效率。你都安装了吗 IntelliJ IDEA 默认安装并提供了非常多的工具&#xff0c;比如 Maven Integration、Markdown support、SSH Remote Run 等。其中有很多好用&#xff0c;但是不为人知的工具。 二 插件列表 阿里代码规约…...

比df更好用的命令!

大家好&#xff0c;我是良许。 对于分析磁盘使用情况&#xff0c;有两个非常好用的命令&#xff1a;du 和 df 。简单来说&#xff0c;这两个命令的作用是这样的&#xff1a; du 命令&#xff1a;它是英文单词 disk usage 的简写&#xff0c;主要用于查看文件与目录占用多少磁…...

【Git使用学习】记录学习过程(1)

安装就省略了&#xff0c;安装结果如下。 Git Bash&#xff1a;这是一个模拟Linux环境的命令行工具&#xff0c;可以使用Git的所有功能。Git GUI&#xff1a;这是一个图形化界面的工具&#xff0c;可以方便地执行Git的常用操作。Git CMD&#xff1a;这是一个Windows命令行工具&…...

K_A18_001 基于STM32等单片机采集MQ2传感参数串口与OLED0.96双显示

K_A18_001 基于STM32等单片机采集MQ2传感参数串口与OLED0.96双显示一、资源说明二、基本参数参数引脚说明三、驱动说明IIC地址/采集通道选择/时序对应程序:四、部分代码说明1、接线引脚定义1.1、STC89C52RCMQ2传感参模块1.2、STM32F103C8T6MQ2传感参模块五、基础知识学习与相关…...

【云原生·Docker】常用命令

目录 &#x1f341;1、管理命令 &#x1f341;2、帮助命令 &#x1f341;3、镜像命令 &#x1f341;4、容器命令 &#x1f342;4.1.查看容器 &#x1f342;4.2.创建容器 &#x1f342;4.3.删除容器 &#x1f342;4.4.拷贝文件 &#x1f342;4.5.查看容器IP &#x1f341;5、部署…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

面向无人机海岸带生态系统监测的语义分割基准数据集

描述&#xff1a;海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而&#xff0c;目前该领域仍面临一个挑战&#xff0c;即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

区块链技术概述

区块链技术是一种去中心化、分布式账本技术&#xff0c;通过密码学、共识机制和智能合约等核心组件&#xff0c;实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点&#xff1a;数据存储在网络中的多个节点&#xff08;计算机&#xff09;&#xff0c;而非…...

软件工程 期末复习

瀑布模型&#xff1a;计划 螺旋模型&#xff1a;风险低 原型模型: 用户反馈 喷泉模型:代码复用 高内聚 低耦合&#xff1a;模块内部功能紧密 模块之间依赖程度小 高内聚&#xff1a;指的是一个模块内部的功能应该紧密相关。换句话说&#xff0c;一个模块应当只实现单一的功能…...

02.运算符

目录 什么是运算符 算术运算符 1.基本四则运算符 2.增量运算符 3.自增/自减运算符 关系运算符 逻辑运算符 &&&#xff1a;逻辑与 ||&#xff1a;逻辑或 &#xff01;&#xff1a;逻辑非 短路求值 位运算符 按位与&&#xff1a; 按位或 | 按位取反~ …...

2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案

一、延迟敏感行业面临的DDoS攻击新挑战 2025年&#xff0c;金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征&#xff1a; AI驱动的自适应攻击&#xff1a;攻击流量模拟真实用户行为&#xff0c;差异率低至0.5%&#xff0c;传统规则引…...

PydanticAI快速入门示例

参考链接&#xff1a;https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...