Gson的相关使用

Gson

简述

Gson是Google提供的一个Java库,它可以用来在Java对象以及Json数据之间进行转换,即可以Java对象转化成一个json的表示形式,也可以将json字符串转化为对应等效的Java对象。

相关使用

首先需要引入相关的Maven依赖:

1
2
3
4
5
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.9.1</version>
</dependency>

Gson的解析功能主要是通过Gson对象来完成的。而Gson对象的生成有两种方式,一种是直接new生成一个对象,另一种是通过GsonBuilder来构建一个Gson对象。前者相当于提供一个默认的Gson的对象,而后者可以提供更多的配置,通过调用配置方法来进行设置,最后调用create方法来创建出Gson对象。

有了Gson对象之后,我们就可以调用其中的核心方法,分别是将对象转化为字符串的toJson()以及将字符串转化为对象的fromJson()。下面是简单的使用举例:

1
2
3
4
5
6
7
Gson gson = new Gson();
String json = gson.toJson(new User("xxx", 18));
System.out.println(json); // {"name":"xxx","age":18}

User user = gson.fromJson("{\"name\":\"xxx\",\"age\":18}", User.class);
System.out.println(user.getName()); // xxx
System.out.println(user.getAge()); // 18

对于这里转换的类与对象,官方文档中有如下的几点提示:

  1. 在类中允许使用private的属性,这也是推荐使用的方式
  2. 不需要使用注解来指示包含或者不包含哪些字段,默认会包含当前类以及所有super class中的所有字段
  3. transient修饰的字段不会被json序列化或者反序列化
  4. 空值的处理逻辑分为toJsonfromJson,默认如下:
    • toJson:空值跳过,不输出
    • fromJson:空值处理为类中的null
  5. 编译器创建的字段不会被序列化或者反序列化,这类字段一般是是带$符号的

数组和集合则可以使用如下的操作:

1
2
3
4
5
6
7
8
9
10
Gson gson = new Gson();
String[] strArr = {"a", "b", "c", "d", "e"};
String json = gson.toJson(strArr);
System.out.println(json);

String[] strings = gson.fromJson("[\"a\",\"b\",\"c\",\"d\",\"e\"]", String[].class);

for (String string : strings) {
System.out.println(string);
}

集合的相关使用如下:

1
2
3
4
5
6
7
8
9
10
11
Gson gson = new Gson();

Integer[] ints = {1, 2, 3, 4, 5};
Collection<Integer> lists = Arrays.asList(ints);
String json = gson.toJson(lists);
System.out.println(json);

Type collectionType = new TypeToken<Collection<Integer>>(){}.getType();
// Collection list1 = gson.fromJson("[1,2,3,4,5]", lists.getClass());
// 这样使用会直接报错
Collection<Integer> list2 = gson.fromJson("[1,2,3,4,5]",collectionType);

注意这里的反序列化中类型Type的指定。由于在Java中存在泛型擦除的特性,我们无法直接通过getClass获取到指定的Class对象,而是需要通过其他方式获取到对应的Type。Type本身是一个接口,无法直接通过new得到,这就需要使用到Gson提供的一个TypeToken工具。这里需要注意的是,TypeToken的构造方法被protected修饰,在IDEA中无法通过智能提示选中,我们需要手动import对应的路径import com.google.gson.reflect.TypeToken;

TypeToken的使用就是上面的一行代码。在TypeToken中提供一个getType()方法,我们需要通过这个方法来获取到Type。但是由于TypeToken的构造方法是protected的,限定了只能由子类来访问。因此我们这里实际上是构造了一个匿名内部类,这个内部类继承了TypeToken,从而能够初始化,然后调用getType()。

当然不只是集合,在其他使用到泛型的地方,也都需要利用上面类似的方式来进行泛型类型的指定,例如我们构造了一个泛型的类:

1
2
3
public class Foo <T>{
T value;
}

之后我们需要进行json的序列化和反序列化。

1
2
3
4
5
6
7
8
9
10
Gson gson = new Gson();

Type type = new TypeToken<Foo<User>>() {}.getType();

Foo<User> foo = new Foo<>(new User("xxx", 18));
String json = gson.toJson(foo, type);
System.out.println(json);

Foo<User> foo1 = gson.fromJson("{\"value\":{\"name\":\"xxx\",\"age\":18}}", type);
System.out.println(foo1);

在Gson中,toJson(obj)在默认情况下会调用obj.getClass()来获取类型信息。但是有时候由于泛型擦除无法获取到对应的类型信息,此时我们可以通过上面的方式来获取到对应的Type,然后直接在方法内部指定。

在Scala中也可以使用Gson,不过在Scala中我们可以直接利用classof来获取对应的类型,包括泛型。

参考文章

  1. Google Gson API 介绍与使用
  2. Gson User Guide

Gson的相关使用
http://example.com/2023/02/21/Gson的相关使用/
作者
EverNorif
发布于
2023年2月21日
许可协议