Jaskson处理复杂的泛型对象

参考链接:ObjectMapper转化对象常用方法(转LIst、Map,以及Type、JavaType、constructType的学习)

文章目录

    • 开篇
    • 范例1:List<Map<String, Person>>
    • 范例2:Map<String, List\<Person>>
    • 范例3:JsonResponse<Map\<String,List\<JsonPerson\>>>
    • 结语

开篇

Jackson是一个在Java体系中被广泛使用的Json序列化和反序列化类库,它提供了丰富的API给开发者使用。

@Data
public class DataInfo<T> {private Integer type;private T data;public static void main(String[] args) throws JsonProcessingException {ObjectMapper mapper = new ObjectMapper();DataInfo<Car> dataInfo = new DataInfo<>();dataInfo.setType(1);dataInfo.setData(new Car("奔驰01", "奔驰", "黑色"));String str1 = mapper.writeValueAsString(dataInfo);System.out.println(str1);DataInfo dataInfo1 = mapper.readValue(str1, DataInfo.class);System.out.println(dataInfo1); // 默认是LinkedHashMap类型DataInfo<Car> dataInfo2 = mapper.readValue(str1, new TypeReference<DataInfo<Car>>() {});System.out.println(dataInfo2); // 正确的泛型 DataInfo<Car>, 缺点是不能将Car.class作为参数JavaType javaType = mapper.getTypeFactory().constructParametricType(DataInfo.class, Car.class);DataInfo dataInfo3 = mapper.readValue(str1, javaType);System.out.println(dataInfo3); // 正确的泛型 DataInfo<Car>, 能将Car.class作为参数JavaType carJavaType = mapper.getTypeFactory().constructType(Car.class);JavaType dataInfoCarJavaType = mapper.getTypeFactory().constructParametricType(DataInfo.class, carJavaType);DataInfo dataInfo4 = mapper.readValue(str1, dataInfoCarJavaType);System.out.println(dataInfo4); // 正确的泛型 DataInfo<Car>, 能将Car.class作为参数}}

今天记录下最近利用Jackson处理复杂的泛型对象的心得,其核心就是利用TypeFactory.constructParametricType()方法,从内到外依此构造Type。

范例1:List<Map<String, Person>>
范例2:Map<String, List<Person>>

范例1:List<Map<String, Person>>

假设我有一个对象List<Map<String, Person>>,我先构造对象然后转为字符串。

//init
List<Map<String, Person>> result = new ArrayList<>();
Map<String, Person> map = new HashMap<>();
map.put("lcf", new Person("lcf"));Map<String, Person> map2 = new HashMap<>();
map2.put("hh", new Person("hh"));
result.add(map);
result.add(map2);//toStr
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(result);

然后将其反序列化:

//toObj JsonMappingException,json转化异常
Map map1 = mapper.readValue(s, Map.class);

直接这样转换是会报错的!

需要利用 TypeFactory.constructParametricType()进行JavaType的类型构造:List<Map<String, Person>>

需要注意的是,在构造的时候需要从内到外进行构造:

  1. 先构造Map<String,Person>得到innerType
  2. 再构造List<innerType>

代码如下所示:

//先构造Map<String,Person>得到innerType,第一个参数为外层对象HashMap,第二个参数为String,第三个参数为Person
JavaType innerType = mapper.getTypeFactory().constructParametricType(HashMap.class, String.class, Person.class);
//再构造List<innerType> 
JavaType resultType = mapper.getTypeFactory().constructParametricType(ArrayList.class, innerType);
//反序列化
List<Map<String, Person>> result2 = mapper.readValue(s, resultType);

范例2:Map<String, List<Person>>

//构造  Map<String, List<Person>>
//1.先构造右边部分
JavaType rightType = mapper.getTypeFactory().constructParametricType(ArrayList.class, Person.class);
//2. 再构造全局
JavaType javaType = mapper.getTypeFactory().constructParametricType(HashMap.class, String.class, rightType.getRawClass());
Map<String, List<Person>> o = mapper.readValue(str, javaType);

这里有一个小知识点,注意的是参数类型要匹配:constructParametricType 方法有如下2种声明需要注意:

public JavaType constructParametricType(Class<?> parametrized, Class<?>... parameterClasses) 
public JavaType constructParametricType(Class<?> rawType, JavaType... parameterTypes)

方法中后面的可变形参参数必须一致。
可以查看返利2的 再构造全局,我本来是希望:

JavaType javaType = mapper.getTypeFactory().constructParametricType(HashMap.class, String.class, rightType);

但是IDE提示参数不匹配,认真一查看确实是:一个是Class,一个是JavaType。
所以通过直接getRawClass解决该问题:

//构造  Map<String, List<Person>>
JavaType javaType = mapper.getTypeFactory().constructParametricType(HashMap.class, String.class, rightType.getRawClass());

范例3:JsonResponse<Map<String,List<JsonPerson>>>

// 为什么需要这一层呢?
// 1\. 接口的返回值将会封装为下述结构体,当调用方接受到报文的时候,可以直接优先判断code即返回码,可快速知道这次请求到底是成功还是失败
// 若失败,则直接读取错误信息message,若成功,直接读取data数据。
// 2\. 也是给会报错的代码打个标志,若出错误了,可以快速根据code返回码,判断对应代码是那段出问题,快速定位。@Getter@ToStringstatic class JsonResponse<T> {private String code;private String message;private T data;}@Getter@ToStringstatic class JsonPerson {private String name;private String pwd;}private static void json11(ObjectMapper objectMapper) throws JsonProcessingException {String json11 = "{\n" +"    \"code\": \"success\",\n" +"    \"data\": {\n" +"        \"TestData1\": [\n" +"            {\n" +"                \"name\": \"test-data-name-one\",\n" +"                \"pwd\": \"test-data-pwd-one\"\n" +"            },\n" +"            {\n" +"                \"name\": \"test-data-name-two\",\n" +"                \"pwd\": \"test-data-pwd-two\"\n" +"            }\n" +"        ],\n" +"        \"TestData2\": [\n" +"            {\n" +"                \"name\": \"test-data2-name-one\",\n" +"                \"pwd\": \"test-data2-pwd-one\"\n" +"            },\n" +"            {\n" +"                \"name\": \"test-data2-name-two\",\n" +"                \"pwd\": \"test-data2-pwd-two\"\n" +"            }\n" +"        ]\n" +"    }\n" +"}";// 获取Type的工厂final TypeFactory typeFactory = objectMapper.getTypeFactory();// 因为转化的是JsonResponse<Map<String,List<JsonPerson>>> 类型 由里到外,一层层创建对应类型// 先创建List<JsonPerson> 类型final JavaType listJsonPersonType = typeFactory.constructCollectionType(List.class, JsonPerson.class);// 由于 constructMapType方法有如下两种://  1\. constructMapType(Class<? extends Map> mapClass,Class<?> keyClass, Class<?> valueClass)//  2\. constructMapType(Class<? extends Map> mapClass, JavaType keyType, JavaType valueType)// 对应的key value入参,要不都是class,要不都是JavaType 类型// 因此需要把Map中的String先创建 JavaType 类型final JavaType stringType = typeFactory.constructType(String.class);// 再创建Map<String,List<JsonPerson>> 类型final JavaType mapType = typeFactory.constructMapType(Map.class, stringType, listJsonPersonType);// 再创建JsonResponse<Map<String,List<JsonPerson>>> 类型final JavaType lastType = typeFactory.constructParametricType(JsonResponse.class, mapType);// 反序列化final JsonResponse<Map<String,List<JsonPerson>>> jsonResponse = objectMapper.readValue(json11, lastType);// 得到结果System.out.println(jsonResponse);}

结语

核心思路:从内到外构造类型,一步一步来!

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

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

相关文章

A037-基于Spring Boot的二手物品交易的设计与实现

&#x1f64a;作者简介&#xff1a;在校研究生&#xff0c;拥有计算机专业的研究生开发团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339; 赠送计算机毕业设计600…

EEG+EMG学习系列 (1) :一个基于小波的自动睡眠评分模型

EEGEMG学习系列:一个基于小波的自动睡眠评分模型 0. 引言1. 主要贡献2. 提出的方法2.1 工作框图2.1 正交小波滤波器组2.2 小波分解2.3 特征提取 3. 结果4. 总结欢迎来稿 论文地址&#xff1a;https://www.mdpi.com/1660-4601/19/12/7176 论文题目&#xff1a;An Automated Wave…

自动化运维-检测Linux服务器CPU、内存、负载、IO读写、机房带宽和服务器类型等信息脚本

前言&#xff1a;以上脚本为今年8月1号发布的&#xff0c;当时是没有任何问题&#xff0c;但现在脚本里网络速度测试py文件获取不了了&#xff0c;测速这块功能目前无法实现&#xff0c;后面我会抽时间来研究&#xff0c;大家如果有建议也可以分享下。 脚本内容&#xff1a; #…

H.265流媒体播放器EasyPlayer.js网页直播/点播播放器WebGL: CONTEXT_LOST_WEBGL错误引发的原因

EasyPlayer无插件直播流媒体音视频播放器属于一款高效、精炼、稳定且免费的流媒体播放器&#xff0c;可支持多种流媒体协议播放&#xff0c;无须安装任何插件&#xff0c;起播快、延迟低、兼容性强&#xff0c;使用非常便捷。 EasyPlayer.js能够同时支持HTTP、HTTP-FLV、HLS&a…

OCRSpace申请free api流程

0.OCRSpace概述 OCR.Space是一款功能强大的在线光学字符识别&#xff08;OCR&#xff09;工具。 格式与语言支持广泛&#xff1a;支持多种图片格式&#xff0c;如 JPG、PNG、GIF、PDF 等作为输入。在语言方面&#xff0c;它支持英语、中文、法语、德语等20多种语言的文字识别…

Linux Kernel Programming 2

目录 书写内核框架 起手我们需要理解的是&#xff1a;用户态和内核态 库和系统调用 API 内核空间组件 探索 LKM&#xff08;Linux Kernel Module体系&#xff09; LKM 框架 内核源代码树中的内核模块 modinfo 动手&#xff01;写年轻人的第一个内核模块程序 先试试看&…

机器学习基础04

目录 1.朴素贝叶斯-分类 1.1贝叶斯分类理论 1.2条件概率 1.3全概率公式 1.4贝叶斯推断 1.5朴素贝叶斯推断 1.6拉普拉斯平滑系数 1.7API 2.决策树-分类 2.1决策树 2.2基于信息增益的决策树建立 2.2.1信息熵 2.2.2信息增益 2.2.3信息增益决策树建立步骤 2.3基于基…

ChatGPT学术专用版,一键润色纠错+中英互译+批量翻译PDF

ChatGPT academic项目是由中科院团队基于ChatGPT专属定制。论文润色、语法检查、中英互译、代码解释等可一键搞定&#xff0c;堪称科研神器。 功能介绍 我们以3.5版本为例&#xff0c;ChatGPT学术版总共分为五个区域&#xff1a;输入控制区、输出对话区、基础功能区、函数插件…

fpga 同步fifo

FIFO 基础知识 FIFO&#xff08;First In First Out&#xff0c;即先入先出&#xff09;&#xff0c;是一种数据缓存器&#xff0c;用来实现数据先入先出 的读写方式。在 FPGA 或者 ASIC 中使用到的 FIFO 一般指的是对数据的存储具有先入先出 特性的缓存器&#xff0c;常被用于…

模式:每个服务一个数据库

Pattern: Database per service。 背景 如用微服务架构模式开发一个在线商店应用程序。大多数服务需要在某种数据库中持久化数据。如&#xff0c;订单服务存储订单信息&#xff0c;而客户服务存储客户信息。 问题 微服务应用程序中的数据库架构是什么&#xff1f; 驱动力…

Java 全栈知识体系

包含: Java 基础, Java 部分源码, JVM, Spring, Spring Boot, Spring Cloud, 数据库原理, MySQL, ElasticSearch, MongoDB, Docker, k8s, CI&CD, Linux, DevOps, 分布式, 中间件, 开发工具, Git, IDE, 源码阅读&#xff0c;读书笔记, 开源项目...

WebRTC实现双端音视频聊天(Vue3 + SpringBoot)

目录 概述 相关概念 双端连接整体实现步骤概述 文章代码实现注意点 STUN和TURN服务器的搭建 开发过程描述 后端开发流程 前端开发流程 效果演示 Gitee源码地址 概述 文章描述使用WebRTC技术实现一对一音视频通话。 由于设备摄像头限制&#xff08;一台电脑作测试无法…

机器学习3

六、朴素贝叶斯分类 背景知识&#xff1a;第三大点的第4点&#xff1a;概率 基础定义_数学概率中事件的定义-CSDN博客 1、条件概率 &#x1d443;(&#x1d434;|&#x1d435;)&#x1d443;(&#x1d434;∩&#x1d435;)/&#x1d443;(&#x1d435;) &#xff1a;A事件在…

SpringBoot Data Redis连接Redis-Cluster集群

使用SpringBoot Data Redis无法连接Redis-Cluster集群 最近在研究系统高并发下的缓存架构&#xff0c;因此自己在自己买的云服务器上搭建好Redis 5.0 版本的集群后&#xff0c;使用springboot的 RedisTemplate连接是发现总是访问不到集群节点。上网百度了发现没有好的解决办法&…

网页作业9

<!DOCTYPE html> <html lang"zh-CN"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>服务中心</title><style>* {margin:…

基于yolov8、yolov5的行人检测识别系统(含UI界面、训练好的模型、Python代码、数据集)

摘要&#xff1a;行人检测在交通管理、智能监控和公共安全中起着至关重要的作用&#xff0c;不仅能帮助相关部门实时监控人群动态&#xff0c;还为自动化监控系统提供了可靠的数据支撑。本文介绍了一款基于YOLOv8、YOLOv5等深度学习框架的行人检测模型&#xff0c;该模型使用了…

递归(3)----力扣40组合数2,力扣473火柴拼正方形

给定一个候选人编号的集合 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意&#xff1a;解集不能包含重复的组合。 示例 1: 输入: candidates [10,1,2,7,6,1…

1Panel 推送 SSL 证书到阿里云、腾讯云

本文首发于 Anyeの小站&#xff0c;点击链接 访问原文体验更佳 前言 都用 CDN 了还在乎那点 1 年证书钱么&#xff1f; 开句玩笑话&#xff0c;按照 Apple 的说法&#xff0c;证书有效期不该超过 45 天。那么证书有效期的缩短意味着要更频繁地更新证书。对于我这样的“裸奔”…

通过shell脚本分析部署nginx网络服务

通过shell脚本分析部署nginx网络服务 1.接收用户部署的服务名称 [rootlocalhost xzy]# vim 1.sh [rootlocalhost xzy]# chmod x 1.sh [rootlocalhost xzy]# ./1.sh2.判断服务是否安装 已安装&#xff1b;自定义网站配置路径为/www&#xff1b;并创建共享目录和网页文件&…

tcp 超时计时器

在 TCP&#xff08;传输控制协议&#xff09;中有以下四种重要的计时器&#xff1a; 重传计时器&#xff08;Retransmission Timer&#xff09; 作用&#xff1a;用于处理数据包丢失的情况。当发送方发送一个数据段后&#xff0c;就会启动重传计时器。如果在计时器超时之前没有…