Google 工具类 Gson 的基本使用
Gson 介绍
Google Gson 是一个简单的基于 Java 的库,用于将 Java 对象序列化为 JSON,反之亦然。 它是由 Google 开发的一个开源库。
以下几点说明为什么应该使用这个库
- 标准化 - Gson 是一个由 Google 管理的标准化库。
- 高效 - 这是对 Java 标准库的可靠,快速和高效的扩展。
- 优化 - Gson 库经过高度优化。
- 支持泛型 - 它为泛型提供了广泛的支持。
- 支持复杂的内部类 - 它支持具有深度继承层次结构的复杂对象。
Gson 的特点
这里列出了 Gson 的一些最显着的特点
- 易于使用 - Gson API 提供了一个高级外观来简化常用的用例。
- 无需创建映射 - Gson API 为大部分要序列化的对象提供了默认映射。
- 性能优 - Gson 速度相当快,内存占用量低。 它适用于大型对象图或系统。
- 干净 JSON - Gson 创建一个干净而紧凑的 JSON 结果,它易于阅读。
- 无依赖性 —Gson 库不需要 JDK 以外的任何其他库。
- 开源 - Gson 库是开源的;它是免费提供的。
处理 JSON 的方法
Gson 提供了三种处理 JSON 的替代方法 -
流媒体 API
它读取和写入 JSON 内容作为离散事件。 JsonReader 和 JsonWriter 将数据读取 / 写入令牌,称为 JsonToken。
这是处理 JSON 的三种方法中最强大的方法。 它具有最低的开销,并且在读 / 写操作中速度非常快。 它类似于用于 XML 的 Stax 解析器。树模型
它准备 JSON 文档的内存树表示。 它构建了一个 JsonObject 节点树。 这是一种灵活的方法,类似于 XML 的 DOM 解析器。
数据绑定
它使用属性访问器将 JSON 转换为 POJO (普通旧 Java 对象) 并从中转换。 Gson 使用数据类型适配器读取 / 写入 JSON。 它类似于 XML 的 JAXB 解析器。
Gson 链接
- GitHub:https://github.com/google/gson
- 用户指南:https://sites.google.com/site/gson/gson-user-guide
Gson 引入
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.6</version>
</dependency>
Gson 入门程序
Gson 是 Google Gson 库的主要操作类。 它提供了将 Java 对象转换为匹配的 JSON 结构的功能,反之亦然。
Gson 首先使用 GsonBuilder
构建,然后使用 toJson(Object)
或 fromJson(String,Class)
方法读取 / 写入 JSON 构造。
使用
GsonBuilder
创建 Gson 对象
创建一个 Gson 对象。 它是一个可重用的对象。GsonBuilder builder = new GsonBuilder(); builder.setPrettyPrinting(); Gson gson = builder.create();
将 JSON 反序列化为对象
使用fromJson()
方法从 JSON 获取对象。 传递 Json 字符串 / Json 字符串的源和对象类型作为参数。//Object to JSON Conversion Student student = gson.fromJson(jsonString, Student.class);
将对象序列化为 JSON
使用toJson()
方法获取对象的 JSON 字符串表示形式。//Object to JSON Conversion jsonString = gson.toJson(student);
示例如下:
String jsonString = "{\"name\":\"Maxsu\", \"age\":24}";
GsonBuilder builder = new GsonBuilder();
builder.setPrettyPrinting();
Gson gson = builder.create();
Student student = gson.fromJson(jsonString, Student.class);
System.out.println(student);
jsonString = gson.toJson(student);
System.out.println(jsonString);
Gson 序列化
对象序列化
序列化写入:
private void writeJSON(Student student) throws IOException {
GsonBuilder builder = new GsonBuilder();
Gson gson = builder.create();
FileWriter writer = new FileWriter("student.json");
writer.write(gson.toJson(student));
writer.close();
}
序列化读取:
private Student readJSON() throws FileNotFoundException {
GsonBuilder builder = new GsonBuilder();
Gson gson = builder.create();
BufferedReader bufferedReader = new BufferedReader(new FileReader("student.json"));
Student student = gson.fromJson(bufferedReader, Student.class);
return student;
}
数组序列化
// 序列化
int[] marks1 = {100,90,85};
System.out.println("marks:" + gson.toJson(marks1));
// 反序列化
int[] marks2 = gson.fromJson("[100,90,85]", int[].class);
System.out.println("marks:" + Arrays.toString(marks2));
集合序列化
// 序列化
List<Integer> marks = Arrays.asList(1,2,3,4,5);
System.out.println("marks:" + gson.toJson(marks));
// 反序列化
Type listType = new TypeToken<List<Integer>>(){}.getType();
marks = gson.fromJson("[100,90,85]", listType);
System.out.println("marks:" +marks);
泛型序列化
Gson 使用 Java 反射 API 来获取要将 Json 文本映射到的对象的类型。 但是在泛型中,这些信息在序列化过程中丢失了。
为了解决这个问题,Gson 提供了一个 com.google.gson.reflect.TypeToken
类来存储通用对象的类型。
Gson gson = new Gson();
// 创建泛型对象
Shape<Circle> shape = new Shape<Circle>();
Circle circle = new Circle(5.0);
shape.setShape(circle);
// 定义 TypeToken
Type shapeType = new TypeToken<Shape<Circle>>() {}.getType();
// 序列化
String jsonString = gson.toJson(shape, shapeType);
System.out.println(jsonString); // {"shape":{"radius":5.0}}
// (错误)通过 类 反序列化
Shape shape1 = gson.fromJson(jsonString, Shape.class);
System.out.println(shape1.get().getClass()); // class com.google.gson.internal.LinkedTreeMap
System.out.println(shape1.get().toString()); // {radius=5.0}
System.out.println(shape1.getArea()); // 0.0
// (正确)通过 TypeToken 反序列化
Shape shape2 = gson.fromJson(jsonString, shapeType);
System.out.println(shape2.get().getClass()); // class demo.google.gson.Circle
System.out.println(shape2.get().toString()); // Circle
System.out.println(shape2.getArea()); // 78.5
其中:
class Shape <T> {
public T shape;
public void setShape(T shape) {
this.shape = shape;
}
public T get() {
return shape;
}
public double getArea() {
if(shape instanceof Circle) {
return ((Circle) shape).getArea();
} else {
return 0.0;
}
}
}
class Circle {
private double radius;
public Circle(double radius){
this.radius = radius;
}
public String toString() {
return "Circle";
}
public double getRadius() {
return radius;
}
public void setRadius(double radius) {
this.radius = radius;
}
public double getArea() {
return (radius*radius*3.14);
}
}
内部类序列化
Person person = new Person();
person.setRollNo(1);
Person.Name name = person.new Name();
name.firstName = "Mahesh";
name.lastName = "Kumar";
person.setName(name);
Gson gson = new Gson();
String jsonString = gson.toJson(person);
System.out.println(jsonString); // {"rollNo":1,"name":{"firstName":"Mahesh","lastName":"Kumar"}}
// 主类
person = gson.fromJson(jsonString, Person.class);
System.out.println(person.getRollNo() +":"+ person.getName().firstName +":"+ person.getName().lastName); // 1:Mahesh:Kumar
// 内部类
String nameString = gson.toJson(name);
System.out.println(nameString); // {"firstName":"Mahesh","lastName":"Kumar"}
name = gson.fromJson(nameString, Person.Name.class);
System.out.println(name.getClass()); // class demo.google.gson.Person$Name
System.out.println(name.firstName + ":" + name.lastName); // Mahesh:Kumar
其中:
class Person {
private int rollNo;
private Name name;
public int getRollNo() {
return rollNo;
}
public void setRollNo(int rollNo) {
this.rollNo = rollNo;
}
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
class Name {
public String firstName;
public String lastName;
}
}
Gson 从序列化中排除字段
使用 excludeFieldsWithModifiers ()
GsonBuilder 使用序列化 / 反序列化过程中的 excludeFieldsWithModifiers()
方法提供对使用特定修饰符排除字段的控制。
GsonBuilder builder = new GsonBuilder();
builder.excludeFieldsWithModifiers(Modifier.TRANSIENT);
Gson gson = builder.create();
使用 @Expose 注解
Gson 提供 @Expose
注解来根据其范围控制类的 Json 序列化 / 反序列化。
类属性中具有
@Expose
支持的变量的类。class Student2 { @Expose private int rollNo; @Expose private String name; private boolean verified; private int id; public static String className; }
在这个类中,
name
和rollno
变量将被暴露以进行序列化。使用
GsonBuilder.excludeFieldsWithoutExposeAnnotation()
方法来指示只有暴露的变量要被序列化 / 反序列化。GsonBuilder builder = new GsonBuilder(); builder.excludeFieldsWithoutExposeAnnotation(); Gson gson1 = builder.create();
Gson 数据绑定
数据绑定 API 用于使用属性访问器或使用注释将 JSON 转换为 POJO (普通旧 Java 对象) 以及从 POJO (普通旧 Java 对象) 转换。
它有两种类型,分别如下所示:
- 原始数据绑定 - 将 JSON 转换为 Java 地图,列表,字符串,数字,布尔值和 NULL 对象。
- 对象数据绑定 - 从任何 JAVA 类型转换 JSON。
Gson 为这两种类型的数据绑定读 / 写 JSON。 数据绑定类似于 XML 的 JAXB 解析器。
原始数据绑定
基元数据绑定是指将 JSON 映射到 JAVA 核心数据类型和内置集合。
Gson 提供了各种内置适配器,可用于序列化 / 反序列化原始数据类型。
Gson gson = new Gson();
String name = "Maxsu";
long rollNo = 1;
boolean verified = false;
int[] marks = { 100, 90, 85 };
// 序列化
System.out.println("{");
System.out.println("name: " + gson.toJson(name) + ",");
System.out.println("rollNo: " + gson.toJson(rollNo) + ",");
System.out.println("verified: " + gson.toJson(verified) + ",");
System.out.println("marks:" + gson.toJson(marks));
System.out.println("}");
// 反序列化
name = gson.fromJson("\"Maxsu\"", String.class);
rollNo = gson.fromJson("1", Long.class);
verified = gson.fromJson("false", Boolean.class);
marks = gson.fromJson("[100,90,85]", int[].class);
对象数据绑定
对象数据绑定是指将 JSON 映射到任何 JAVA 对象。
Gson gson = new Gson();
Student student = new Student();
student.setAge(26);
student.setName("Maxsu");
String jsonString = gson.toJson(student);
System.out.println(jsonString);
Student student1 = gson.fromJson(jsonString, Student.class);
System.out.println(student1);
Gson 树模型
从 JSON 创建树
在读取 JSON 之后,JsonParser
提供了一个指向树的根节点的指针。根节点可以用来遍历整个树。
下面的代码片段来获取提供的 JSON 字符串的根节点。
JsonParser parser = new JsonParser();
String jsonString = "{\"name\":\"Maxsu\", \"age\":26,\"verified\":false,\"marks\": [100,90,85]}";
// 从JSON创建树
JsonElement rootNode = parser.parse(jsonString);
遍历树模型
在遍历树并处理数据时,使用到根节点的相对路径获取每个节点。
以下代码片段显示了如何遍历树。
// 遍历树模型
if (rootNode.isJsonObject()) {
JsonObject details = rootNode.getAsJsonObject();
JsonElement nameNode = details.get("name");
System.out.println("Name: " + nameNode.getAsString());
JsonElement ageNode = details.get("age");
System.out.println("Age: " + ageNode.getAsInt());
JsonElement verifiedNode = details.get("verified");
System.out.println("Verified: " + (verifiedNode.getAsBoolean() ? "Yes" : "No"));
JsonArray marks = details.getAsJsonArray("marks");
for (int i = 0; i < marks.size(); i++) {
JsonPrimitive value = marks.get(i).getAsJsonPrimitive();
System.out.print(value.getAsInt() + " ");
}
}
Gson 数据流
Streaming API 用于通过令牌读取 JSON 令牌。 它读取和写入 JSON 内容作为离散事件。
JsonReader
和 JsonWriter
将数据读取 / 写入令牌,称为 JsonToken
。
这是处理 JSON 的三种方法中最强大的方法。 它具有最低的开销,并且在读 / 写操作中速度非常快。 它类似于用于 XML 的 Stax 解析器。
下面,我们将展示使用 GSON streaming API 来读取 JSON 数据。 Streaming API 与令牌的概念一起工作,Json 的每个细节都要仔细处理。
// 创建JsonReader对象,并将其传递给json文本。
JsonReader reader = new JsonReader(new StringReader(jsonString));
// 开始读取
reader.beginObject();
// 获取下一个
JsonToken token = reader.peek();
// 检查类型
if (token.equals(JsonToken.NAME)) {
// 获取内容
fieldname = reader.nextName();
}
Gson 自定义类型适配器
Gson 使用其内置适配器执行对象的序列化 / 反序列化。 它也支持自定义适配器。
创建自定义适配器
通过扩展 TypeAdapter
类并传递目标类型的对象来创建自定义适配器。
重写读写方法分别执行自定义的反序列化和序列化。
class StudentAdapter extends TypeAdapter<Student> {
@Override
public Student read(JsonReader reader) throws IOException {
...
}
@Override
public void write(JsonWriter writer, Student student) throws IOException {
}
}
注册自定义适配器
使用 GsonBuilder
注册自定义适配器并使用 GsonBuilder
创建一个 Gson 实例。
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Student.class, new StudentAdapter());
Gson gson = builder.create();
完整示例
public class CustomAdaptersDemo {
public static void main(String args[]) {
GsonBuilder builder = new GsonBuilder();
builder.registerTypeAdapter(Worker.class, new WorkerAdapter());
builder.setPrettyPrinting();
Gson gson = builder.create();
String jsonString = "{\"name\":\"Maxsu\", \"rollNo\":1}";
Worker worker = gson.fromJson(jsonString, Worker.class);
System.out.println(worker);
jsonString = gson.toJson(worker);
System.out.println(jsonString);
}
}
class WorkerAdapter extends TypeAdapter<Worker> {
@Override
public Worker read(JsonReader reader) throws IOException {
Worker worker = new Worker();
reader.beginObject();
String fieldname = null;
while (reader.hasNext()) {
JsonToken token = reader.peek();
if (token.equals(JsonToken.NAME)) {
fieldname = reader.nextName();
}
if ("name".equals(fieldname)) {
token = reader.peek();
worker.setName(reader.nextString());
}
if ("rollNo".equals(fieldname)) {
token = reader.peek();
worker.setRollNo(reader.nextInt());
}
}
reader.endObject();
return worker;
}
@Override
public void write(JsonWriter writer, Worker worker) throws IOException {
writer.beginObject();
writer.name("name");
writer.value(worker.getName());
writer.name("rollNo");
writer.value(worker.getRollNo());
writer.endObject();
}
}
class Worker {
private int rollNo;
private String name;
public int getRollNo() {
return rollNo;
}
public void setRollNo(int rollNo) {
this.rollNo = rollNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String toString() {
return "Worker[ name = " + name + ", roll no: " + rollNo + "]";
}
}
Gson 空对象支持
Gson 默认生成优化的 Json 内容,忽略 NULL
值。
但是 GsonBuilder
提供的标志使用 GsonBuilder.serializeNulls()
方法在 Json 输出中显示 NULL
值。
// 默认
Gson gson1 = new Gson();
demo(gson1); // {"age":1}
// 使用serializeNulls
GsonBuilder builder = new GsonBuilder();
builder.serializeNulls();
builder.setPrettyPrinting();
Gson gson2 = builder.create();
demo(gson2); // {"name": null, "age": 1 }
其中,
public static void demo(Gson gson) {
Student student = new Student();
student.setAge(1);
String jsonString = gson.toJson(student);
System.out.println(jsonString);
}
Gson 版本支持
Gson 提供了 @Since
注解来控制基于其各种版本的类的 Json 序列化 / 反序列化。
以下具有版本支持的类:
class Demo {
@Since(1.0)
private int rollNo;
@Since(1.0)
private String name;
@Since(1.1)
private boolean verified;
public int getRollNo() {
return rollNo;
}
public void setRollNo(int rollNo) {
this.rollNo = rollNo;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void setVerified(boolean verified) {
this.verified = verified;
}
public boolean isVerified() {
return verified;
}
}
进行 Json 序列化 / 反序列化:
// 构建对象
Demo demo = new Demo();
demo.setRollNo(1);
demo.setName("Maxsu");
demo.setVerified(true);
// 默认
Gson gson1 = new Gson();
String jsonString1 = gson1.toJson(demo);
System.out.println(jsonString1); // {"rollNo":1,"name":"Maxsu","verified":true}
// 版本支持
GsonBuilder builder = new GsonBuilder();
builder.setVersion(1.0);
Gson gson2 = builder.create();
String jsonString2 = gson2.toJson(demo);
System.out.println(jsonString2); // {"rollNo":1,"name":"Maxsu"}
参考链接
- https://www.yiibai.com/gson