Gson详解(一)

一.Gson说明

Gson(又称Google Gson)是Google公司发布的一个开放源代码的Java库,主要用途为序列化Java对象为JSON字符串,或反序列化JSON字符串成Java对象。而JSON(JavaScriptObject Notation) 是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成,广泛应用于各种数据的交互中,尤其是服务器与客户端的交互。
引入依赖:

<dependency><groupId>com.google.code.gson</groupId><artifactId>gson</artifactId><version>2.8.5</version>
</dependency>

二.Gson使用
2.1Gson的创建
Gson的创建方式一:直接new Gson对象
// 使用new方法

Gson gson = new Gson();

// toJson 将bean对象转换为json字符串

String jsonStr = gson.toJson(user, User.class);

// fromJson 将json字符串转为bean对象

Student user= gson.fromJson(jsonStr, User.class);

// 序列化List

String jsonStr2 = gson.toJson(list);

// 反序列化成List时需要使用到TypeToken getType()

List<User> retList = gson.fromJson(jsonStr2,new TypeToken<List<User>>(){}.getType());

//type的使用,User代表解析出来的Bean对象,result为后台返回的json格式字符串,
//List代表通过Gson按照type格式解析json格式字符串后返回的对象列表
如:Type type = new TypeToken<List>() {
}.getType();
List UserBeans = gson.fromJson(result, type);

Gson的创建方式二:使用GsonBuilder

使用new Gson(),此时会创建一个带有默认配置选项的Gson实例,如果不想使用默认配置,那么就可以使用GsonBuilder。

//serializeNulls
//serializeNulls()是GsonBuilder提供的一种配置,当字段值为空或null时,依然对该字段进行转换
Gson gson = new GsonBuilder().serializeNulls().create();

使用GsonBuilder创建Gson实例的步骤:

首先创建GsonBuilder,然后调用GsonBuilder提供的各种配置方法进行配置,

最后调用GsonBuilder的create方法,将基于当前的配置创建一个Gson实例。

GsonBuilder的一些配置:
Gson gson = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation() //不对没有用@Expose注解的属性进行操作
.enableComplexMapKeySerialization() //当Map的key为复杂对象时,需要开启该方法
.serializeNulls() //当字段值为空或null时,依然对该字段进行转换
.setDateFormat(“yyyy-MM-dd HH:mm:ss:SSS”) //时间转化为特定格式
.setPrettyPrinting() //对结果进行格式化,增加换行
.disableHtmlEscaping() //防止特殊字符出现乱码
.registerTypeAdapter(User.class,new UserAdapter()) //为某特定对象设置固定的序列或反序列方式,自定义Adapter需实现JsonSerializer或者JsonDeserializer接口
.create();

2.2Gson基本使用

Gson提供了fromJson() 和toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化;同时每个方法都提供了重载方法

(1)基本数据类型的解析

Gson gson = new Gson();
int i = gson.fromJson("100", int.class); //100
double d = gson.fromJson("\"99.99\"", double.class);  //99.99
boolean b = gson.fromJson("true", boolean.class);     // true
String str = gson.fromJson("String", String.class);   // String

(2)基本数据类型的生成

Gson gson = new Gson();
String jsonNumber = gson.toJson(100);       // 100
String jsonBoolean = gson.toJson(false);    // false
String jsonString = gson.toJson("String"); //"String"

(3)POJO类的生成与解析

public class User {//省略其它public String name;public int age;public String emailAddress;
}
Gson gson = new Gson();
User user = new User("张三",24);
String jsonObject = gson.toJson(user); // {"name":"张三kidou","age":24}

解析JSON:

Gson gson = new Gson();
String jsonString = "{\"name\":\"张三\",\"age\":24}";
User user = gson.fromJson(jsonString, User.class);

2.3属性重命名 @SerializedName 注解的使用

从上面POJO的生成与解析可以看出json的字段和值是的名称和类型是一一对应的,但也有一定容错机制(如第一个例子第3行将字符串的99.99转成double型),但有时候也会出现一些不和谐的情况,如:

期望的json格式:{“name”:“张三”,“age”:24,“emailAddress”:“zhangsan@ceshi.com”}

实际:{“name”:“张三”,“age”:24,“email_address”:“zhangsan@ceshi.com”}

Gson在序列化和反序列化时需要使用反射,一般各类库都将注解放到annotations包下,打开源码在com.google.gson包下有一个annotations,里面有一个SerializedName的注解类。对于json中email_address这个属性对应POJO的属性则变成:
@SerializedName(“email_address”)
public String emailAddress;

为POJO字段提供备选属性名**:**SerializedName注解提供了两个属性,上面用到了其中一个,别外还有一个属性alternate,接收一个String数组

注:alternate需要2.4版本
@SerializedName(value = “emailAddress”, alternate = {“email”, “email_address”})
public String emailAddress;
//当三个属性(email_address、email、emailAddress)都中出现任意一个时均可以得到正确的结果

//当多种情况同时出时,以最后一个出现的值为准。
Gson gson = new Gson();
String json = “{“name”:“张三kidou”,“age”:24,“emailAddress”:“zhangsan@ceshi.com”,“email”:“zhangsan_2@ceshi.com”,“email_address”:“zhangsan_3@ceshi.com”}”;
User user = gson.fromJson(json, User.class);
System.out.println(user.emailAddress); // zhangsan_3@example.com

2.4Gson中使用泛型

例如:JSON字符串数组:[“Android”,“Java”,“PHP”]

当要通过Gson解析这个json时,一般有两种方式:使用数组,使用List;而List对于增删都是比较方便的,所以实际使用是还是List比较多

数组比较简单:
Gson gson = new Gson();
String jsonArray = “[“Android”,“Java”,“PHP”]”;
String[] strings = gson.fromJson(jsonArray, String[].class);

对于List将上面的代码中的 String[].class 直接改为 List.class 是不行的,对于Java来说List 和List 这俩个的字节码文件只一个那就是List.class,这是Java泛型使用时要注意的问题 泛型擦除

为了解决的上面的问题,Gson提供了TypeToken来实现对泛型的支持,所以将以上的数据解析为List时需要这样写

Gson
Gson gson = new Gson();
String jsonArray = “[“Android”,“Java”,“PHP”]”;
String[] strings = gson.fromJson(jsonArray, String[].class);
List stringList = gson.fromJson(jsonArray, new TypeToken<List>() {}.getType());
//TypeToken的构造方法是protected修饰的,所以上面才会写成new TypeToken<List>() {}.getType() 而不是 new TypeToken<List>().getType()

泛型解析对接口POJO的设计影响

泛型的引入可以减少无关的代码:
我们真正需要的data所包含的数据,而code只使用一次,message则几乎不用,如果Gson不支持泛型或不知道Gson支持泛型的同学一定会这么定义POJO
public class UserResponse {
public int code;
public String message;
public User data;
}

当其它接口的时候又重新定义一个XXResponse将data的类型改成XX,很明显code,和message被重复定义了多次,通过泛型可以将code和message字段抽取到一个Result的类中,这样只需要编写data字段所对应的POJO即可:
public class Result {
public int code;
public String message;
public T data;
}
//对于data字段是User时则可以写为 Result ,当是个列表的时候为 Result<List>

2.5Gson的流式反序列化

(1)自动方式

Gson提供了fromJson()和toJson() 两个直接用于解析和生成的方法,前者实现反序列化,后者实现了序列化。同时每个方法都提供了重载方法
Gson.toJson(Object);
Gson.fromJson(Reader,Class);
Gson.fromJson(String,Class);
Gson.fromJson(Reader,Type);
Gson.fromJson(String,Type);

(2)手动方式:手动的方式就是使用stream包下的JsonReader类来手动实现反序列化,和Android中使用pull解析XML是比较类似的
String json = “{“name”:“张三”,“age”:“24”}”;
User user = new User();
JsonReader reader = new JsonReader(new StringReader(json));
reader.beginObject();
while (reader.hasNext()) {
String s = reader.nextName();
switch (s) {
case “name”:
user.name = reader.nextString();
break;
case “age”:
user.age = reader.nextInt(); //自动转换
break;
case “email”:
user.email = reader.nextString();
break;
}
}
reader.endObject(); // throws IOException
System.out.println(user.name); //张三
System.out.println(user.age); // 24
System.out.println(user.email); //zhangsan@ceshi.com

自动方式最终都是通过JsonReader来实现的,如果第一个参数是String类型,那么Gson会创建一个StringReader转换成流操作

2.6Gson的流式序列化*

(1)自动方式

Gson.toJson方法列表

//PrintStream(System.out) 、StringBuilder、StringBuffer和*Writer都实现了Appendable接口。
Gson gson = new Gson();
User user = new User(“张三”,24,“zhangsan@ceshi.com”);
gson.toJson(user,System.out);

(2)手动方式
JsonWriter writer = new JsonWriter(new OutputStreamWriter(System.out));
writer.beginObject() // throws IOException
.name(“name”).value(“张三”)
.name(“age”).value(24)
.name(“email”).nullValue() //演示null
.endObject(); // throws IOException
writer.flush(); // throws IOException
//{“name”:“张三”,“age”:24,“email”:null}
//除了beginObject、endObject还有beginArray和endArray,两者可以相互嵌套,注意配对即可。beginArray后不可以调用name方法,同样beginObject后在调用value之前必须要调用name方法。

2.7使用GsonBuilder导出null值、格式化输出、日期时间

一般情况下Gson类提供的 API已经能满足大部分的使用场景,但有时需要更多特殊、强大的功能时,这时候就引入一个新的类 GsonBuilder。

GsonBuilder从名上也能知道是用于构建Gson实例的一个类,要想改变Gson默认的设置必须使用该类配置Gson

GsonBuilder用法:
//各种配置 //生成配置好的Gson
Gson gson = new GsonBuilder().create();

(1)Gson在默认情况下是不动导出值null的键的,如:
public class User {

 public String name;public int age;

//省略
public String email;

}
Gson gson = new Gson();
User user = new User(张三",24);
System.out.println(gson.toJson(user)); //{“name”:“张三”,“age”:24}
//email字段是没有在json中出现的,当在调试时需要导出完整的json串时或API接中要求没有值必须用Null时,就会比较有用。

使用方法:
Gson gson = new GsonBuilder().serializeNulls() .create();
User user = new User(“张三”, 24);
System.out.println(gson.toJson(user)); //{“name”:“张三”,“age”:24,“email”:null}

格式化输出、日期时间及其它:
Gson gson = new GsonBuilder()
//序列化null
.serializeNulls()
// 设置日期时间格式,另有2个重载方法
// 在序列化和反序化时均生效
.setDateFormat(“yyyy-MM-dd”)
// 禁此序列化内部类
.disableInnerClassSerialization()
//生成不可执行的Json(多了 )]}’ 这4个字符)
.generateNonExecutableJson()
//禁止转义html标签
.disableHtmlEscaping()
//格式化输出
.setPrettyPrinting()
.create();

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

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

相关文章

第十五章 解读argparse模块用法实例(工具)

argsparse是python的命令行解析的标准模块&#xff0c;内置于python&#xff0c;不需要安装。这个库可以让我们直接在命令行中就可以向程序中传入参数并让程序运行。 港真的&#xff0c;今天是我第一次学习argsparse。因为用不到&#xff0c;自然也就没有学习的动力。但是现在…

C语言-内存函数详解

文章目录 1. memcpy使用和模拟实现2. memmove使用和模拟实现3. memset函数的使用4. memcmp函数的使用 1. memcpy使用和模拟实现 返回类型和参数&#xff1a; void * memcpy ( void * destination, const void * source, size_t num );1.函数memcpy从source的位置开始向后复制…

R语言实现Lasso回归

一、Lasso回归 Lasso 回归&#xff08;Least Absolute Shrinkage and Selection Operator Regression&#xff09;是一种用于线性回归和特征选择的统计方法。它在回归问题中加入了L1正则化项&#xff0c;有助于解决多重共线性&#xff08;多个特征高度相关&#xff09;和特征选…

设备树是什么?

设备树&#xff1a; 设备树DTS(Device Tree Source) 描述设备信息的独立的文件。 为什么要引入设备树&#xff1f; 随着芯片的发展&#xff0c;Linux内核中就包含着越来越多这些描述设备的代码&#xff0c;导致Linux内核代码会很臃肿。因此引入了设备树文件&#xff0c;从…

基于 GPS 定位信息的 Pure-Pursuit 轨迹跟踪实车测试(1)

基于 GPS 定位信息的 Pure-Pursuit 轨迹跟踪实车测试&#xff08;1&#xff09; 进行了多组实验&#xff0c;包括顺逆时针转向&#xff0c;直线圆弧轨迹行驶&#xff0c;以及Pure-Pursuit 轨迹跟踪测试 代码修改 需要修改的代码并不多&#xff0c;主要对 gps_sensor 功能包和…

Java中的泛型是什么?如何使用泛型类和泛型方法?

Java 中的泛型是一种编程机制&#xff0c;允许你编写可以与多种数据类型一起工作的代码&#xff0c;同时提供编译时类型检查以确保类型的安全性。泛型的主要目的是提高代码的可重用性、类型安全性和程序的整体性能。 泛型类&#xff08;Generic Class&#xff09;: 在泛型类中…

【教3妹学编程-算法题】统计子串中的唯一字符

3妹&#xff1a;“太阳当空照&#xff0c;花儿对我笑&#xff0c;小鸟说早早早&#xff0c;你为什么背上炸药包” 2哥 :3妹&#xff0c;什么事呀这么开发。 3妹&#xff1a;2哥你看今天的天气多好啊&#xff0c;阳光明媚、万里无云、秋高气爽&#xff0c;适合秋游。 2哥&#x…

关于python中的nonlocal关键字

如果在函数的子函数中需要调用外部变量&#xff0c;一般会看见一个nonlocal声明&#xff0c;类似下面这种&#xff1a; def outer_function():x 10def inner_function():nonlocal xx 1print(x)inner_function()outer_function()在这个例子中&#xff0c;inner_function 引用…

【DevOps】基于 KubeSphere 的 Kubernetes 生产实践之旅(万字长文)

基于 KubeSphere 的 Kubernetes 生产实践 1.KubeSphere 简介1.1 全栈的 Kubernetes 容器云 PaaS 解决方案1.2 选型理由&#xff08;从运维的角度考虑&#xff09; 2.部署架构图3.节点规划3.1 软件版本3.2 规划说明3.2.1 K8s 集群规划3.2.2 存储集群3.2.3 中间件集群3.2.4 网络规…

SpringBoot——LiteFlow引擎框架

优质博文&#xff1a;IT-BLOG-CN 一、LiteFlow 简介 LiteFlow是一个轻量且强大的国产规则引擎框架&#xff0c;可用于复杂的组件化业务的编排领域。帮助系统变得更加丝滑且灵活。利用LiteFlow&#xff0c;你可以将瀑布流式的代码&#xff0c;转变成以组件为核心概念的代码结构…

计算机组成原理-Cache的基本概念和原理

文章目录 存储系统存在的问题Cache的工作原理局部性原理性能分析例题界定何为局部部分问题总结 存储系统存在的问题 增加Cache层来缓和CPU和主存的工作速度矛盾 Cache的工作原理 启动某个程序后&#xff0c;将程序的代码从辅存中取出放入内存中&#xff0c;再从内存中将代码…

【安全】2.6.6版本的audit审计机制分析

文章目录 2.6.6版本的audit审计机制分析1 关于内核版本2 入口3 audit初始化4 系统调用审计流程5 配置下发流程6 总结 2.6.6版本的audit审计机制分析 1 关于内核版本 linux内核从2.6.6版本开始支持audit机制&#xff0c;为了更好的理解audit本身的机制&#xff0c;需要对audit…

机器人开发的选择

喷涂机器人 码垛机器人 纸箱码垛机器人 焊接机器人 跳舞机器人 管道清理机器人 工地巡检机器人 点餐机器人 化工巡检机器人 装箱机器人 安防巡检机器人 迎宾机器人好像有点像软银那个 污水管道检测机器人 大酒店用扫地机器人 家用扫地机器人 工厂用&#xff08;…

知识图谱06——将pdf中的表格(文字形式)保存至csv中

使用ubuntu22.04&#xff0c;anaconda 由于装环境装了一阵子&#xff0c;不确定装了哪些包了 可能的环境安装 conda install -c conda-forge pymupdf conda install -c conda-forge camelot-py conda install pandas #或者 pip install PyMuPDF pip install camelot-py[all] …

求链表环的起始位置

leetcode中题目位置 https://leetcode.cn/problems/linked-list-cycle-ii/submissions/?envTypestudy-plan-v2&envIdtop-100-liked 代码&#xff1a; public class Solution {public ListNode detectCycle(ListNode head) {if (head null || head.next null) {return…

S25FL系列FLASH读写的FPGA实现

文章目录 实现思路具体实现子模块实现top模块 测试Something 实现思路 建议读者先对 S25FL-S 系列 FLASH 进行了解&#xff0c;我之前的博文中有详细介绍。 笔者的芯片具体型号为 S25FL256SAGNFI00&#xff0c;存储容量 256Mb&#xff0c;增强高性能 EHPLC&#xff0c;4KB 与 6…

Could not resolve all files for configuration ‘:app:androidJdkImage‘.

在使用./gradlew build编译项目时候遇到了该问题&#xff0c;整体错误如下: * What went wrong: Configuration cache state could not be cached: field generatedModuleFile of com.android.build.gradle.tasks.JdkImageInput bean found in field compilerArgumentProvider…

Leetcode199. 二叉树的右视图

Every day a Leetcode 题目来源&#xff1a;199. 二叉树的右视图 解法1&#xff1a;层序遍历 给定一个二叉树的 根节点 root&#xff0c;想象自己站在它的右侧&#xff0c;按照从顶部到底部的顺序&#xff0c;返回从右侧所能看到的节点值。 按层序遍历&#xff0c;将每层的…

如何判断一个题目用“贪心/动态规划“还是用“BFS/DFS”方法解决

1 总结 1.1 贪心、动态规划和BFS/DFS题解的关系 一般能使用贪心、动态规划解决一个问题时&#xff0c;使用BFS&#xff0c;DFS也能解决这个题&#xff0c;但是反之不能成立。 1.2 2 贪心 -> BFS/DFS 2.1 跳跃游戏1和3的异同 这两道题&#xff0c;“跳跃游戏”&#xf…

html实现各种瀑布流(附源码)

文章目录 1.设计来源1.1 动态响应瀑布流1.2 分页瀑布流1.3 响应瀑布流 2.效果和源码2.1 动态效果2.2 源代码 源码下载 作者&#xff1a;xcLeigh 文章地址&#xff1a;https://blog.csdn.net/weixin_43151418/article/details/134613121 html实现各种瀑布流(附源码)&#xff0c;…