# gson
## gson简介
gson是一个java库,通常用来将java对象转化为其json表示的字符串,或者将json格式的字符串转化为其等价的java对象。
## gson使用
在gson中,使用最频繁的类是Gson。可以通过new Gson()构造函数来创建Gson对象,也可以通过GsonBuilder来创建Gson对象,GsonBuidler在创建Gson对象时能够指定一些设置,如版本控制等。
由于Gson对象在执行json操作时并不会保存任何状态,故而Gson对象是线程安全的,单一的Gson对象可以在多线程环境下被重复使用。
### Gson库通过Maven引入
```xml
com.google.code.gson
gson
2.9.1
compile
```
### 基本类型的序列化和反序列化
```java
// Serialization
Gson gson = new Gson();
gson.toJson(1); // ==> 1
gson.toJson("abcd"); // ==> "abcd"
gson.toJson(new Long(10)); // ==> 10
int[] values = { 1 };
gson.toJson(values); // ==> [1]
// Deserialization
int one = gson.fromJson("1", int.class);
Integer one = gson.fromJson("1", Integer.class);
Long one = gson.fromJson("1", Long.class);
Boolean false = gson.fromJson("false", Boolean.class);
String str = gson.fromJson("\"abc\"", String.class);
String[] anotherStr = gson.fromJson("[\"abc\"]", String[].class);
```
### 对象的序列化和反序列化
类似于java自带的序列化机制,当成员字段被transient修饰时,并不会序列化该字段
```java
class BagOfPrimitives {
private int value1 = 1;
private String value2 = "abc";
private transient int value3 = 3;
BagOfPrimitives() {
// no-args constructor
}
}
// Serialization
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);
// ==> json is {"value1":1,"value2":"abc"}
// Deserialization
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
// ==> obj2 is just like obj
```
### gson和对象联用的使用规范
- gson使用过程中,待序列化或反序列化的成员字段可以是private的,同时也推荐将待序列化或反序列化的成员字段声明为private
- 没有必要对成员字段使用注解来特定标明在序列化或者反序列化中包含该字段,默认情况下该对象所有成员字段和该对象父类对象所包含的所有字段都会被序列化
- 类似于jdk自带的序列化和反序列化机制,如果一个字段被标明为transient,该字段将不会被包含到序列化和反序列化过程中
- gson实现能够正确处理字段为空的情况
- 当序列化过程中,为null的字段将会被省略
- 当反序列化过程中,如果一个字段在json串中并没有被设置,反序列化得到的对象中该字段将会被设置为默认值:引用类型默认值为null、数字类型默认值为0,boolean类型其默认值为false
- 在内部类、匿名类、本地类中关联外部类的字段将会被忽略,并不会包含在序列化和反序列化过程中
### gson和嵌套类的关联使用
gson可以单独的对静态内部类进行序列化和反序列化,因为静态内部类并不包含对外部类的引用;但是gson无法单独的反序列化内部类,因为在反序列化内部类的过程中,其无参构造器需要一个指向其外部类对象的引用,但是该外部类对象在对内部类进行反序列化时是不可访问的。
可以通过将内部类改为静态的内部类,此时对内部类的反序列化将不会需要指向外部类对象的引用。
### gson和数组的关联使用
gson支持多维数组,并且支持任意的复杂元素类型
```java
Gson gson = new Gson();
int[] ints = {1, 2, 3, 4, 5};
String[] strings = {"abc", "def", "ghi"};
// Serialization
gson.toJson(ints); // ==> [1,2,3,4,5]
gson.toJson(strings); // ==> ["abc", "def", "ghi"]
// Deserialization
int[] ints2 = gson.fromJson("[1,2,3,4,5]", int[].class);
// ==> ints2 will be same as ints
```
### gson对java中的集合进行序列化和反序列化
gson可以序列化任意对象的集合,但是无法对其进行反序列化,因为在反序列化时用户没有任何方法去指定其生成的集合中元素的类型。因而,需要通过typeToken来告知Gson需要反序列化的类型。
```java
Gson gson = new Gson();
Collection ints = Arrays.asList(1,2,3,4,5);
// Serialization
String json = gson.toJson(ints); // ==> json is [1,2,3,4,5]
// Deserialization
Type collectionType = new TypeToken>(){}.getType();
Collection ints2 = gson.fromJson(json, collectionType);
// ==> ints2 is same as ints
```
### gson对Map类型的序列化和反序列化
默认情况下,gson会将java中任意的Map实现类型序列化为JSON对象。由于JSON对象其key只支持字符串类型,gson会将待序列化的Map key调用toString转化为字符串。如果map中的key为null,则序列化后的key为"null"
```java
/**
* gson对map进行序列化
**/
Gson gson = new Gson();
Map stringMap = new LinkedHashMap<>();
stringMap.put("key", "value");
stringMap.put(null, "null-entry");
// Serialization
String json = gson.toJson(stringMap); // ==> json is {"key":"value","null":"null-entry"}
Map intMap = new LinkedHashMap<>();
intMap.put(2, 4);
intMap.put(3, 6);
// Serialization
String json = gson.toJson(intMap); // ==> json is {"2":4,"3":6}
```
在反序列化的过程中,gson会使用为Map key类型注册的TypeAdapter的read方法来进行反序列化。为了让gson知道反序列化得到的Map对象的key和value类型,需要使用TypeToken。
```java
Gson gson = new Gson();
Type mapType = new TypeToken