Gson反序列化原理

前言

序列化和反序列化是日常工作中经常使用的工具,一般用于对象的持久化保存或者对象的网络传输,一般有两种情况,一种是对象本身实现了Serializable接口,这种情况下可以利用jdk自带的功能或者Kryo等这种封装好的序列化反序列化工具,还有一种情况就是对象本身并没有实现Serializable接口,那么这个时候开发者们就会考虑将对象序列化为字符串来进行持久化保存或传输。

笔者在日常开发中常用到的序列化工具就是谷歌的Gson和阿里巴巴的FastJson,这两种的区别在上一篇博客中通过实验的方式做了一个简单对比。那么本篇来着重探究一下Gson是如何反序列化对象的。

Gson反序列化对象实现的实现原理

我们先来考虑一个问题,如果有这样一个json字符串{“name”:“cz”,“age”:18},在没有现成的反序列化工具时,我们要如何将该json字符串中的内容映射到对象中呢?
对象的结构如下:

public class Student {public String name;  // 特别注意这里修饰符为publicpublic String home;public Integer age;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getHome() {return home;}public void setHome(String home) {this.home = home;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}
}
方法一:

通过反射调用set方法来设置值。
代码如下:

/**
* @author Chengzhi
* @date 2023-08-23
* @测试目的:测试通过set方法来反序列化对象
* @预期结果:
*/
@Test
public void test2() throws IllegalAccessException, InstantiationException, InvocationTargetException {String json = "{"name":"cz","age":18}";String[] fields = json.substring(1,json.length()-1).split(",");Map<String, Object> map = new HashMap<String, Object>();for (String field : fields) {String[] split = field.split(":");String key = split[0];String value = split[1];if (key.startsWith(""") && key.endsWith(""")) {key = split[0].substring(1,split[0].length()-1);}if (value.startsWith(""") && value.endsWith(""")) {value = split[1].substring(1,split[1].length()-1);}map.put(key.toUpperCase(), value);}Class<Student> studentClass = Student.class;Student o = studentClass.newInstance();Method[] methods = studentClass.getMethods();for (Method method : methods) {String methodName = method.getName();if (methodName.startsWith("set")) {String key = methodName.substring(3, methodName.length()).toUpperCase();Class<?> parameterType = method.getParameterTypes()[0];Object value = map.get(key);if ("java.lang.Integer".equals(parameterType.getName())) {value = Integer.valueOf((String) value);}method.invoke(o, value);}}System.out.println(o.getName());
}
方法二:

在本案例中由于对象的变量是使用public修饰的,那么同样的我可以通过反射直接赋值。
代码如下:

/*** @author Chengzhi* @date 2023-08-24* @测试目的: 通过反射直接给对象的变量赋值* @预期结果:*/
@Test
public void test3() throws IllegalAccessException, InstantiationException {String json = "{"name":"cz","age":18}";String[] jsonFields = json.substring(1,json.length()-1).split(",");Map<String, Object> map = new HashMap<String, Object>();for (String field : jsonFields) {String[] split = field.split(":");String key = split[0];String value = split[1];if (key.startsWith(""") && key.endsWith(""")) {key = split[0].substring(1,split[0].length()-1);}if (value.startsWith(""") && value.endsWith(""")) {value = split[1].substring(1,split[1].length()-1);}map.put(key.toUpperCase(), value);}Class<Student> studentClass = Student.class;Student o = studentClass.newInstance();Field[] fields = studentClass.getFields();for (Field field : fields) {String name = field.getName();Object value = map.get(name.toUpperCase());if ("java.lang.Integer".equals(field.getGenericType().getTypeName())) {value = Integer.valueOf((String) value);}field.set(o, value);}System.out.println(o.getName());
}
上述方式存在的问题

上述方式一其实就是阿里巴巴的FastJson实现原理,而第二种实现方式由于示例POJO类中的变量都是使用public修饰的,可以直接反射赋值,但是,正常的对象都是不允许使用public修饰,因为这样值很容易被改变。如果pojo类中的变量使用private修饰,由于访问权限的约束,Field[] fields = studentClass.getFields();这里会获取不到参数值。最终不会赋值成功。

Gson反序列化原理

其实Gson反序列化原理和方式二思路很接近,都是直接去操作POJO类的全局变量,而不是去调用set方法,那么Gson是如何绕过变量修饰符的权限约束呢。从源码可以发现Gson是利用Unsafe类的putObject方法。

//为给定地址设置值,忽略修饰限定符的访问限制,与此类似操作还有: putInt,putDouble,putLong,putChar等
public native void putObject(Object o, long offset, Object x);

该方法可以忽略修饰符的权限约束。

image.png

总结

Gson利用反射的思想结合强大的Unsafe类,通过直接改变类的变量值来达到反序列化的目的。

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

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

相关文章

Elasticsearch:什么是大语言模型 (LLMs)?

假设你想参加流行的游戏节目 Jeopardy&#xff08;这是一个美国电视游戏节目&#xff0c;参赛者将获得答案并必须猜测问题&#xff09;。 要参加演出&#xff0c;你需要了解任何事情的一切。 所以你决定在接下来的三年里每天都花时间阅读互联网上的所有内容。 你很快就会意识到…

关于 Invalid bound statement (not found): 错误的解决

关于 Invalid bound statement not found: 错误的解决 前言错误原因解决方法1. 检查SQL映射文件2. 检查MyBatis配置3. 检查SQL语句4. 检查命名约定5. 清除缓存6. 启用日志记录 重点注意 结语 我是将军我一直都在&#xff0c;。&#xff01; 前言 当开发Java Spring Boot应用程…

挚文集团:股票回购速度、收入指引均不及预期,令投资者失望

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 挚文集团未来将不再公布MAU数据 今年6月初&#xff0c;挚文集团(MOMO)在公布2023年第一季度业绩时透露&#xff0c;“陌陌应用的月活跃用户(MAU)”已经从去年3月的1.109亿下降到了今年3月的1.065亿&#xff0c;同比下降了-…

2023,简历石沉大海?软件测试岗位真的已经饱和了....

各大互联网公司的接连裁员&#xff0c;政策限制的行业接连消失&#xff0c;让今年的求职雪上加霜&#xff0c;想躺平却没有资本&#xff0c;还有人说软件测试岗位饱和了&#xff0c;对此很多求职者深信不疑&#xff0c;因为投出去的简历回复的越来越少了。 另一面企业招人真的…

执行事务合伙人和法人区别是什么

1. 定义不同&#xff1a; 执行事务合伙人指负责经营和管理合伙企业的人&#xff0c;对外代表合伙企业进行业务活动&#xff0c;对内负责合伙企业的日常管理。 法人则是企业的法定代表人&#xff0c;代表企业参与民事活动&#xff0c;是企业的行政领导&#xff0c;对企业经济活动…

MAT查找类(岔路口)-技巧

文章目录 前言一、现状二、使用步骤1.导出 hprof2.用MAT打开3.细节操作找大对象的线程名称查看线程的详情查找类的GC Roots柳暗花明检验真理 总结 前言 又是java 内存溢出 OOM JAVA MAT 分析工具大大的好。 高效查找问题根源&#xff0c;才是硬道理。 一、现状 mat 打开hprof…

CVE-2017-7529 Nginx越界读取内存漏洞

漏洞概述 当使用Nginx标准模块时&#xff0c;攻击者可以通过发送包含恶意构造range域的header请求&#xff0c;来获取响应中的缓存文件头部信息。在某些配置中&#xff0c;缓存文件头可能包含后端服务器的IP地址或其它敏感信息&#xff0c;从而导致信息泄露。 影响版本 Ngin…

vue3后台管理框架之技术栈

vue3全家桶技术 基础构建&#xff1a; vue3vite4TypeScript 代码格式 &#xff1a; eslintprettystylelint git生命周期钩子&#xff1a; husky css预处理器&#xff1a; sass ui库&#xff1a; element-plus 模拟数据: mock 网络请求&#xff1a; axios 路由&#xff1a; vue…

Three.js图案溶解shader

上图提供两种方式溶解显示 上面一排是根据现实的图案红色通道也就是r值进行溶解 下面一排提供额外的溶解纹理 可以通过简单更改呈现多种溶解图案 代码仓库 gitee b站账号&#xff1a;https://space.bilibili.com/374230437 interface IMapPath {map: string;dissolve?: string…

基于antd实现动态修改节点的Tree组件

前言 之前遇到一个需求&#xff0c;可对于任意节点添加或删除子节点。首先技术栈是基于reactant design&#xff0c;ant提供了Tree组件&#xff0c;但都是根据固定的数据渲染出树结构&#xff0c;如果需要新增或删除节点&#xff0c;官网并未提供。 实现过程 新增节点 首先…

910数据结构(2013年真题)

算法设计题 问题1 已知元素数据类型为整数的顺序表SL&#xff08;a1,a2,…,am,b1,b2,…,bn&#xff09;&#xff0c;试设计算法将SL中元素的两部分互换为&#xff08;b1,b2,…,bn,a1,a2,…,am&#xff09;。要求&#xff1a;不能使用额外的数组空间。 &#xff08;1&#xff…

使用 Python 和蒙特卡罗计算未来股价走势以及历史波动率和隐含波动率

一、简介 预测金融市场是定量精度和全球经济细微差别的复杂融合。在这一探索中,蒙特卡罗模拟脱颖而出,成为首要的统计工具,指导我们对未来股票价格的理解。 这种方法以摩纳哥著名的蒙特卡洛赌场命名,并不依靠运气,而是植根于严格的概率模型。想象一下在受控环境中精心策划…

前端开发工具有哪些?17款前端工程师必备工具推荐!

软件开发是一个高度专业化的职业分工&#xff0c;根据所使用的编程语言的不同&#xff0c;会细分出多种岗位&#xff1a;前端开发、后端开发、客户端开发、iOS开发、Android开发、数据库开发等等&#xff0c;具体到每一个岗位&#xff0c;工作中常用的工具软件也存在着差别。 …

0基础学习VR全景平台篇 第108篇:全景图细节处理(下,航拍)

上课&#xff01;全体起立~ 大家好&#xff0c;欢迎观看蛙色官方系列全景摄影课程&#xff01; &#xff08;调色前图库&#xff09; &#xff08;原图-大图&#xff09; 一、导入文件 单击右下角导入按钮&#xff0c;选择航拍图片所在文件夹&#xff0c;选择图片&#xff0…

【前端】Js

目 录 一.前置知识第一个程序JavaScript 的书写形式注释输入输出 二.语法概览变量的使用理解 动态类型基本数据类型 三.运算符算术运算符赋值运算符 & 复合赋值运算符自增自减运算符比较运算符逻辑运算符位运算移位运算 四.条件语句if 语句三元表达式switch 五.循环语句whi…

基于php 进行每半小时钉钉预警

前言 业务场景&#xff1a;监控当前业务当出现并发情况时技术人员可以可以及时处理 使用技术栈&#xff1a; laravelredis 半小时触发一次报警信息实现思路 1、xshell脚本 具体参数就不详细解释了&#xff0c;想要详细了解可以自行百度 curl -H "Content-Type:appl…

论文阅读/写作扫盲

第一节&#xff1a;期刊科普 JCR分区和中科院分区是用于对期刊进行分类和评估的两种常见方法。它们的存在是为了帮助学术界和研究人员更好地了解期刊的学术质量、影响力和地位。 JCR分区&#xff08;Journal Citation Reports&#xff09;&#xff1a;JCR分区是由Clarivate Ana…

有哪些值得推荐的优秀 HTMLCSS 网站前端设计的网络资源(博客、论坛)?

前言 推荐几个有意思的CSS学习的网站和github上的学习类型的项目~ 网站推荐 1、CODEPEN 代码与所展示的页面相互对应&#xff0c;你可以在上面找到其他人已经写好的demo&#xff0c;参考 代码效果 网址&#xff1a;https://codepen.io 2、Coding Fantasy 通过游戏的形式来提…

多媒体应用设计师 第7章 多媒体数字压缩编码技术基础

1.多媒体数据压缩技术理论基础及压缩编码方法分类 必要性:大数据量的图像信息会给存储器的存储容量&#xff0c;通信线路的带宽&#xff0c;以及计算机的处理速度增加极大压力。如果没有多媒体编码压缩技术的发展&#xff0c;大容量图像&#xff0c;视频信息的存储和传输就难以…

自助查询小助手

嘿亲爱的老师们&#xff01;还在为成绩发布而烦恼吗&#xff1f;别担心&#xff0c;今天我们来聊聊如何利用免费的老师发布工具&#xff0c;让你轻松解决这一烦恼&#xff01; 成绩查询页面是什么&#xff1f;在很多学校里&#xff0c;成绩查询页面通常是一个网站或应用程序&am…