GSON详解

GSON

GSON弥补了JSON的许多不足的地方,在实际应用中更加适用于Java开发。在这里,我们主要讲解的是利用GSON来操作java对象和json数据之间的相互转换,包括了常见的对象序列化和反序列化的知识。

一、前言

因为json有2种类型:

  • 一种是对象,object -> {key:value,key:value,…} 。
  • 另一种是数组,array -> [value,value,…] 。

所以针对这两种类型,来展开对json数据的操作。

GSON在解析json的时候,大体上有2种类型,一种是直接在内存中生成object或array,通过手工指定key来获取值;另一种是借助javabean来进行映射获取值。

二、对 json 数据进行反序列化,得到java 对象

1、不借助java 类,直接解析json 数据

1.1、json 是对象类型

当ajax传过来的json数据属于对象时,不论这个对象简单还是复杂,都可以轻松地把它们给解析出来。

ajax传过来的json数据(是对象形式):

var data_json =  {"sex": '男',"hobby":["baskte","tennis"],"introduce": {"name":"tom","age":23}};data: JSON.stringify(data_json),

GSON解析:

BufferedReader reader = request.getReader();// 读取json数据StringBuffer buffer = new StringBuffer();String s;while ((s = reader.readLine()) != null) {buffer.append(s);}String json = buffer.toString();System.out.println("json:" + json);  // json解析器,解析json数据JsonParser parser = new JsonParser();JsonElement element = parser.parse(json);// json属于对象类型时if (element.isJsonObject()) {  JsonObject object = element.getAsJsonObject();  // 转化为对象// 1. value为string时,取出stringString sex = object.get("sex").getAsString();                         System.out.println("sex:" + sex);// 2. value为array时,取出arrayJsonArray hobbies = object.getAsJsonArray("hobby");  // for (int i = 0; i < hobbies.size(); i++) {String hobby = hobbies.get(i).getAsString();System.out.println("hobby:" + hobby);}// 3. value为object时,取出objectJsonObject introduce = object.getAsJsonObject("introduce");String name = introduce.get("name").getAsString();int age = introduce.get("age").getAsInt();System.out.println("name:" + name+";age:" + age);}

解读:

很明显,对于传过来的对象类型的json数据,使用GSON是很方便进行解析的,在得到了json数据对应的JsonObject 对象之后,我们就可以很简单地进行操作了。这种方法是直接获取json中的值,而没有进行java对象的还原(简单情况下,没有必要生成相应的javabean)。

1.2、json 是数组类型

ajax传过来的json数据(是数组形式):

var data_json =  ["cake",2,{"brother":"tom","sister":"lucy"},["red","orange"]
];data: JSON.stringify(data_json),

GSON解析:

BufferedReader reader = request.getReader();StringBuffer buffer = new StringBuffer();String s;while ((s = reader.readLine()) != null) {buffer.append(s);}String json = buffer.toString();System.out.println("json:"+json);// json解析器,解析json数据JsonParser parser = new JsonParser();JsonElement element = parser.parse(json);// json属于数组类型if (element.isJsonArray()) {  JsonArray array = element.getAsJsonArray();// 1. value为string时,取出stringString array_1 = array.get(0).getAsString();System.out.println("array_1:"+array_1);// 2. value为int时,取出intint array_2 = array.get(1).getAsInt();System.out.println("array_2:"+array_2);// 3. value为object时,取出objectJsonObject array_3 = array.get(2).getAsJsonObject();String brother = array_3.get("brother").getAsString();String sister = array_3.get("sister").getAsString();System.out.println("brother:"+brother+";sister:"+sister);// 4. value为array时,取出arrayJsonArray array_4 = array.get(3).getAsJsonArray();for (int i = 0; i < array_4.size(); i++) {System.out.println(array_4.get(i).getAsString());}}

解读:

当json是数组类型的时候,使用GSON操作和上一小节几乎差不多,只不过是第一步生成的json对象是数组而已。上面2种方式解析json十分简单,在日常使用中足够了。

但是对于有规律的json数据,比如往往是可以映射成一个javabean对象,那么我们就没有必要一个个手工取值了,我们可以借助javabean配合GSON来更加快速地解析json数据。

2、借助java 类,生成对应java 对象来解析数据

详细的前端json 数据,可以看前面的反例,以下只是使用直接的json数据进行说明。

生成对于的java对象之后,就可以通过getter方法来获取相应的数据了。

通用代码:

在这个方法里,借助json数据来生成java对象的代码都是一致的:

Gson gson = new Gson();
BeanType bean = gson.fronJson(jsonData, BeanType.class);

2.1、 json 是对象类型

2.1.1 基本案列

json 数据

{"name":"tom","salary":2999}

java类

public class MyEntry {private String name;private int age;public String address;public int salary;// getter、setter、toString
}

java 代码

String json1 = "{\"name\":\"tom\",\"salary\":2999}";
Gson gson1 = new Gson();
MyEntry entry1 = gson1.fromJson(json1, MyEntry.class);
System.out.println(entry1.toString());  // name:tom,age:0,address:null,salary:2999

解读

可以看出,对于不完整的json 数据,在我们映射了相应的java 类之后,转化得到的java对象,未赋值的字段都是默认值。这就符合java的规范和常理。

2.1.2 字段名并不一致怎么办?

如果前端传过来的json 数据的key和我们java类的字段不一致,就需要我们在java类中手工进行指定。

@SerializedName() 注解

比如对于上面的json 数据,salary 改成money ,我们得到的java对象中,salary 就会变成默认值:0。

因此,我们要使用注解:

@SerializedName("money")
private String salary;@SerializedName({"money", "salary"})  // 可以有多个备选值
private String salary;
2.1.3 如何限定某个字段不参加序列化或反序列化?

@Expose()注解

如果想要让java类的某些字段不参加序列化或反序列化,可以显示来设置。如:

@Expose(serialize=false,deserialize=false)
private String name;

上面的name 字段将不参加序列化及反序列化。

2.1.4 复合的对象怎么处理?

当json 数据是对象形式时,常见的value 会是一个数组或对象。如:

{"name": "tom","age": 0,"money": 2999,"hobbies": ["basket","tennis"],"collections": {"2": "paint","3": "mouse"}
}

举一反三,value 是数组时(hobbies),对应在java类中也是数组;value 是对象时,对应在java类中就是map(k-v对)了。

因此,我们可以很容易得到对应的java类:

private List<String> hobbies;
private Map<Integer, String> collections;

解读: 可知,再复杂的json 数据,我们也可以构造出对应的java类。

2.2. json 是数组类型

2.2.1 基本案例:

json数据

["apple", "banana", "pear"]

显然,数组在java中对应的也是数组。

java代码

String json2 = "[\"apple\", \"pear\", \"banana\"]";
Gson gson2 = new Gson();
// 传入的java类型是String[].class
String[] fruits = gson2.fromJson(json2, String[].class);  
2.2.2 我想用List 数组

对于上面这种简单的数组形式的json数据,我们还可以反序列化为List类型的数组。因为List进行增删改都比较方便。

这里就要使用泛型了,具体的泛型讲解,会在下面进行说明。

String json2 = "[\"apple\", \"pear\", \"banana\"]";
Gson gson2 = new Gson();
List<String> fruitList = gson2.fromJson(json2, new TypeToken<List<String>>(){}.getType());

3、使用泛型

有的时候,传过来的json数据在格式上是很相近的,只不过某个字段的value不固定,如果为此生成多个相似的java类就十分多余了。

如:前端传过来的json数据主要是2类:

{"code":"0","message":"success","data":{}}
{"code":"0","message":"success","data":[]}

对于字段data ,有时候是对象,有时候是数组。

这里,我们将使用Result 来映射json数据,使用MyEntry 类来映射json 数据的data 部分。这意味着,对于不同的json数据,我们将不再生成多个java类,而是动态生成所需的java对象。

result对象

public class Result<T>{public int code;public String message;public T data;// getter、setter
}

3.1 data为对象的json1:

{"code": 0,"message": "success","data": [{"name": "tom","age": 32,"address": "street one","salary": 4999},{"name": "tom","age": 32,"address": "street one","salary": 4999}]
}

java代码

String typeJson1 = "{\n" +"  \"code\":0,\n" +"  \"message\":\"success\",\n" +"  \"data\":{\n" +"    \"name\":\"tom\",\n" +"    \"age\":32,\n" +"    \"address\":\"street one\",\n" +"    \"salary\":4999\n" +"  }\n" +"}";
Gson typeGson1 = new Gson();
// 动态生成所需的java类的类型
Type type1 = new TypeToken<Result<MyEntry>>(){}.getType();
// 动态生成java对象
Result<MyEntry> result1 = typeGson1.fromJson(typeJson1, type1);
System.out.println(result1);

3.2 data为数值的json2:

{"code": 0,"message": "success","data": [{"name": "tom","age": 32,"address": "street one","salary": 4999},{"name": "lucy","age": 24,"address": "street three","salary": 2333}]
}

java代码

String typeJson2 = "{\n" +"  \"code\": 0,\n" +"  \"message\": \"success\",\n" +"  \"data\": [\n" +"    {\n" +"      \"name\": \"tom\",\n" +"      \"age\": 32,\n" +"      \"address\": \"street one\",\n" +"      \"salary\": 4999\n" +"    },\n" +"    {\n" +"      \"name\": \"lucy\",\n" +"      \"age\": 24,\n" +"      \"address\": \"street three\",\n" +"      \"salary\": 2333\n" +"    }\n" +"  ]\n" +"}";
Gson typeGson2 = new Gson();
// 再次动态生成java类型
Type type2 = new TypeToken<Result<List<MyEntry>>>(){}.getType();
// 再次动态生成java对象
Result<List<MyEntry>> result2 = typeGson2.fromJson(typeJson2, type2);
System.out.println(result2);

四、java 对象序列化为json 数据

这一部分,主要是讲解如何将一个java对象序列化为json数据,也会涉及到如何组装这个java对象。

4.1、由具体的java类对象,序列化为json 数据

我们可以直接把java对象给序列化为json数据。对于未设置的属性,会采取默认值;但是如果默认是null的话,该属性就不会被序列化。

java类,我们仍然采用的是MyEntry 类。

MyEntry entry2 = new MyEntry();
entry2.setName("tom");
entry2.setSalary(2999);
List<String> hobbies = new ArrayList<>();
hobbies.add("basket");
hobbies.add("tennis");
entry2.setHobbies(hobbies);
Map<Integer, String> collections = new HashMap<>();
collections.put(2, "paint");
collections.put(3, "mouse");
entry2.setCollections(collections);
Gson gson2 = new Gson();
String json2 = gson2.toJson(entry2);
System.out.println(json2);
// {"name":"tom","age":0,"money":2999,"hobbies":["basket","tennis"],"collections":{"2":"paint","3":"mouse"}}

对于非值属性,即引用属性,如hobbies、collections,如果没有设置值的话,在序列化后的json数据中,是不会出现的。而如果是值属性的话,没有设置值的情况下,在json数据中会是使用java中的默认值。

4.1.1 要生成对象形式的json 数据

  • 第一种方法是上面的,直接使用java类对象
  • 还可以使用生成map对象,进行序列化

4.1.2 要生成数组形式的json 数据

  • 第一种,使用String[] 字符串数组来生成
  • 还可以使用List对象来序列化
  • 还可以使用Set对象来序列化

对于序列化的要求,更多的情况会使用注解来选择需要/不需要进行序列化的字段。

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

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

相关文章

机器人 瓷砖墙面清洗_墙壁清洁机器人解析

1第一章绪论1.1课题的背景、目的及意义[1]壁面清洗爬壁机器人属于移动式服务机器人的一种&#xff0c;可在垂直壁面或顶部移动&#xff0c;完成其外表面的清洗作业。在工业机器人问世30多年后的今天&#xff0c;它已被世人看作是一种生产工具&#xff0c;在制造、装配及最近在服…

内存回收算法与 Hot Spot 算法实现细节

文章目录内存回收算法概述对象存活判定算法引用计数算法可达性分析算法垃圾收集算法分代收集理论标记-清除算法标记-复制算法半区复制算法Appel 式复制算法Appel 式复制算法的逃生门设计标记-整理算法HotSpot 虚拟机实现细节GC Root 枚举Hot Spot 实现 GC Root 枚举安全点与安全…

link st 量产工具_ST-Link资料03_ST-Link固件升级、驱动下载安装方法

说明&#xff1a;本文原创作者『strongerHuang』本文首发于微信公众号『嵌入式专栏』&#xff0c;同时也更新在我的个人网站&#xff1a;EmbeddedDevelop一、写在前面前两篇文章讲述的都是关于ST-Link的一些理论知识&#xff0c;建议初学者看看&#xff1a;ST-Link资料01_ST-Li…

Java 主流垃圾收集器

文章目录垃圾收集器概述Serial 与 Serial Old 垃圾收集器Serial 与 Serial Old 垃圾收集器总结ParNew 垃圾收集器Parallel Scavenge 垃圾收集器Parallel Scavenge 的吞吐量控制参数Parallel Scavenge 的自适应调节策略Parallel Scavenge 垃圾收集器总结ParNew 和 Parallel Scav…

SSM 框架整合 spring 发送邮件功能实现!

基于SSM的 spring 发送邮件的实现 由于考虑到项目中需要&#xff0c;如果程序出现异常或其它问题&#xff0c;可以发送邮件来及时提醒后台维护人员处>理。所以目前考虑使用JavaMail来实现邮件发送&#xff01;如下&#xff0c;是我整理的一些内容&#xff0c;做个笔记记录下…

Java 故障处理与性能监控工具

文章目录概述基础工具jpsjstatjinfojmapjhatjstack高级工具VisualVMVisualVM 的主要功能ArthasGC Easy概述 在使用 Java 语言进行开发的过程中&#xff0c;我们很可能会遇到各种程序问题。 比如&#xff0c;可能会遇见程序突然就静止不动了&#xff0c;但是程序进程依然显示在…

SSM整合框架实现发送邮件功能

SSM整合框架实现发送邮件功能 1.导入发送邮件的依赖 <!-- 发送邮件jar包--><!--spring支持--><dependency><groupId>org.springframework</groupId><artifactId>spring-context-support</artifactId><version>5.0.0.RELE…

ap接口 php_2018年小米高级 PHP 工程师面试题(模拟考试卷)

点击蓝字关注我们&#xff01;每天获取最新的编程小知识&#xff01;源 / php中文网 源 / www.php.cn在面试之前多看看有关公司的面试资料&#xff0c;对之后的面试会很有帮助。今天就给大家带来2018年小米高级 PHP 工程师面试题(模拟考试卷)&#xff0c;有着一定的参考价…

composer 设置版本号_Composer依赖管理 – PHP的利器

别再到处搜PHP类扩展包了&#xff0c;对于现代语言而言&#xff0c;包管理器基本上是标配。Java 有 Maven&#xff0c;Python 有 pip&#xff0c;Ruby 有 gem&#xff0c;Nodejs 有 npm。PHP 的则是 PEAR&#xff0c;不过 PEAR 坑不少&#xff1a;依赖处理容易出问题配置非常复…

LeetCode.31 下一个排列

题目描述 实现获取下一个排列的算法&#xff0c;算法需要将给定的数组&#xff0c;重新排列成下一个更大的排列&#xff08;即组合出下一个更大的数字&#xff09;。 如果不存在下一个更大的排列&#xff0c;则将数字重新排列成最小的排列。 题目思路 我们可以使用如下的思路…

SpringBoot2.5.4发送邮件4种方式

一.准备 在创建SpringBoot项目 二、选择依赖 选择依赖时 发现其选择依赖时有邮件发送与Springboot整合的jar包&#xff0c;我们勾选即可 如果未勾选也不要紧&#xff0c;咱们手动导入 <dependency><groupId>org.projectlombok</groupId><artifactId…

手游传奇刷元宝_传奇手游 平民制霸刀刀爆元宝!

新轩辕神途手游游戏介绍新轩辕神途是一款玩法种类十分丰富多样的神途手游&#xff0c;游戏内拥有放置挂机升级玩法&#xff0c;玩家不用浪费时间工作上学都能自动升级打宝&#xff0c;更有十分庞大的世界地图等你来探索&#xff0c;十分靠谱&#xff0c;更受欢迎&#xff0c;爆…

MySQL 逻辑架构与常用的存储引擎

文章目录概述逻辑架构示意图Server 层功能模块连接器查询缓存分析器优化器执行器存储引擎层InnoDBInnoDB 主要特性InnoDB 引擎下的查询过程MyISAMMyISAM 的主要特性MyISAM 引擎下的查询过程InnoDB 和 MyISAM 的对比概述 MySQL 是我们平时开发中最常用的关系型数据库&#xff0…

java 阿里云接口实现发送短信验证码

1.先去阿里云开通短信服务&#xff1a; 2.添加模板及签名&#xff1a;需要审核&#xff0c;个人账户审核就几分钟就OK 先解释一下模板及签名&#xff1a; 标准参照&#xff1a;https://help.aliyun.com/document_detail/55324.html?spm5176.sms-sign.0.0.765c1cbeNhvWBZ 去…

faiss python安装_faiss入门

Faiss入门篇假定Faiss已经被安装&#xff0c;若未安装可参考小编安装编译篇https://zhuanlan.zhihu.com/p/78689463。本篇小编基于Faiss的官方wiki实例展开&#xff0c;旨在让大家快速入门Faiss。Faiss底层用c实现并为用户提供python接口&#xff0c;本篇我们以python示例Faiss…

MySQL 索引底层数据结构实现

文章目录概述讨论范围查询数据结构查询数据结构种类及其高性能查询原理MySQL 索引的底层数据结构MySQL 索引的需求分析选择 MySQL 索引的底层数据结构B- 树和 B 树的对比MySQL 索引的底层数据结构揭秘概述 MySQL 的索引是存储引擎用于快速找到记录的一种数据结构&#xff0c;是…

Java面试——SpringMVC系列总结

文章目录&#xff1a; 1.什么是Spring MVC&#xff1f; 2.Spring MVC的主要组件有哪些&#xff1f; 3.请描述一下Spring MVC的工作流程&#xff1f; 4.MVC是什么&#xff1f;MVC设计模式的好处有哪些 5.拦截器Interceptor与过滤器Filter有什么区别&#xff1f; 6.Spring …

中蒙俄经济走廊背景_上海外国语大学师生代表团参观访问G60科创走廊俄罗斯院士创新基地...

10月23日&#xff0c;上海外国语大学团委书记、创新创业与实践教育学院执行院长廖文其、俄罗斯东欧中亚学院党总支副书记郝佳、辅导员石朝天及学生代表等一行15人参观访问G60科创走廊俄罗斯院士创新基地(下简称&#xff1a;创新基地)。创新基地主任赵磊、俄罗斯中小企业联合会华…

MySQL 索引类别与索引使用指南

文章目录概述MySQL 索引类型MySQL 索引方法BTREE 方法HASH 方法主键构成的索引结构主键索引的优点主键索引的缺点依赖顺序插入更新代价高索引使用指南索引树回顾索引树排序规则最左前缀法则最左前缀法则的产生依据最左前缀法则延申字段书写顺序不影响最左前缀法则最左前缀法则总…

测试员不可不知的几款bug管理工具

根据每个公司性质的不同&#xff0c;规模的不同&#xff0c;所用到的bug管理工具也可能不同。你们用的bug管理工具是什么呢&#xff1f;下面介绍几款主流的bug管理工具&#xff1a; 1. JIRA&#xff08;付费&#xff09; JIRA的生产者把JIRA定义为Professional Issue Tracker&…