Gson源码分析

来源:互联网 发布:漂流木帆布包 淘宝 编辑:程序博客网 时间:2024/05/16 11:00

开源库地址:https://github.com/google/gson 
解读版本:2.7

Gson是一个可以用来将Java对象转换为JSON字符串的Java库。当然,它也可以把JSON字符串转换为等价的Java对象。网上已经有了不少可将Java对象转换成JSON的开源项目。但是,大多数都要求你在Java类中加入注解,如果你无法修改源码的话就比较坑爹了,此外大多数开源库并没有对泛型提供完全的支持。于是,Gson在这两个重要的设计目标下诞生了。Gson可以作用于任意的Java对象(包括接触不到源码的),与此同时还加入了完整的泛型支持。

基本用法

  • 基本数据类型
// 序列化为jsonGson gson = new Gson();gson.toJson(1);            // ==> 1gson.toJson("abcd");       // ==> "abcd"gson.toJson(new Long(10)); // ==> 10int[] values = { 1 };gson.toJson(values);       // ==> [1]// 反序列化为java objectint 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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 对象
public class User {    public String name="maplejaw";    public int age=18;    public User(){     //无参构造方法    }}// 序列化 User obj = new User(); Gson gson = new Gson(); String json = gson.toJson(obj);  // ==> json is {"name":"maplejaw","age":18}//反序列化 User obj2 = gson.fromJson(json, User.class);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 泛型
Type type= new TypeToken<List<User>>(){}.getType();List<User> list = gson.fromJson(json, type);
  • 1
  • 2
  • 1
  • 2
  • 配置Gson
  Gson gson=new GsonBuilder()                 .setLenient() //设置宽松的容错性                 .setPrettyPrinting() //设置漂亮的打印(打印出来的有缩进风格)                 .setVersion(..) //设置当前版本号                 ...                 .create();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

Gson的基本用法如上所示,使用起来比较简便,一般情况下也已经够用了。需要注意的是,Java对象一定要有一个无参构造方法,这是Gson实例化对象的关键(自定义实例后面介绍)。此外,Java对象中并不要求有set/get方法。一般只要了解以上基本用法就能够应付绝大多数情况了,如果想深入了解一些高级用法,请继续往下阅读源码解读。

源码解读

Gson中的5个注解

  • @Expose 
    表示某个成员变量暴露于JSON序列化/反序列化。只需在GsonBuilder中配置excludeFieldsWithoutExposeAnnotation()时才会生效。当配置过后,只有使用了@Expose注解的成员变量才会参与序列化/反序列化工作。

    public class User {@Exposeprivate String firstName;//参与序列化(JAVA对象转为JSON)/反序列化(JSON转为JAVA对象)@Expose(serialize = false) private String lastName;//参与反序列化@Expose (serialize = false, deserialize = false) private String emailAddress; //不参与private String password;//不参与}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
  • @SerializedName 
    表示某个成员变量序列化/反序列化的名字,无需在GsonBuilder中配置就能生效,甚至会覆盖掉FieldNamingPolicy

    public class MyClass {@SerializedName("name") //a => nameString a;@SerializedName(value="name1", alternate={"name2", "name3"}) String b;String c;public MyClass(String a, String b, String c) { this.a = a; this.b = b; this.c = c;}}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    当使用了该注解后,此时序列化/反序列化的情况如下:

    MyClass target = new MyClass("v1", "v2", "v3");Gson gson = new Gson();String json = gson.toJson(target);//===== 输入的json如下 ====={"name":"v1","name1":"v2","c":"v3"}//同理,以下的json数据都能成功反序列化为MyClass。{"name":"v1","name1":"v2","c":"v3"}{"name":"v1","name2":"v2","c":"v3"}{"name":"v1","name3":"v2","c":"v3"}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    这个注解有什么好处呢?众所周知,在Java中的变量命名规则须遵守驼峰原则,但是,如果后台使用的是PHP等其他语言,将导致命名规则不一致;又或者因为其他原因导致多条json只有一个字段不一致,总不能建立多个实体类吧?这时候这个注解就派上用场了。

  • @Since 
    表示某个成员变量从哪个版本开始生效,只在GsonBuilder中配置了setVersion()时才会生效。

    public class User {private String firstName;//一直参与private String lastName;//一直参与@Since(1.0) private String emailAddress; //当前版本>=1.0时才会参与序列化/反序列化,否则忽略@Since(1.0) private String password;//当前版本>=1.0时才会参与序列化/反序列化,否则忽略@Since(1.1) private Address address;//当前版本>=1.1时才会参与序列化/反序列化,否则忽略}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • @Until 
    表示某个成员变量从哪个版本开始失效,只在GsonBuilder中配置了setVersion()时才会生效。

     public class User {  private String firstName;//一直参与  private String lastName;//一直参与  @Until(1.1) private String emailAddress;//当前版本<=1.1时参加序列化/反序列化  @Until(1.1) private String password;//当前版本<=1.1时参加序列化/反序列化 }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • @JsonAdapter 
    表示在某一个成员变量或者类上使用TypeAdapter。至于TypeAdapter是什么东东,后面介绍。举个例子: 
    假如有个User类如此下:

     public class User {  public final String firstName, lastName;  private User(String firstName, String lastName) {    this.firstName = firstName;    this.lastName = lastName; }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    准备编写一个UserJsonAdapter。

    public class UserJsonAdapter extends TypeAdapter<User> {@Override public void write(JsonWriter out, User user) throws IOException { out.beginObject(); out.name("name"); out.value(user.firstName + " " + user.lastName); out.endObject();}@Override public User read(JsonReader in) throws IOException { in.beginObject(); in.nextName(); String[] nameParts = in.nextString().split(" "); in.endObject(); return new User(nameParts[0], nameParts[1]);}}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    将UserJsonAdapter应用到属性:此时,Gadget中的User,将会按照UserJsonAdapter来进行序列化/反序列化

    private static final class Gadget {@JsonAdapter(UserJsonAdapter.class)public User user;}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    将UserJsonAdapter应用到类:此时,在序列化/反序列User对象时,都会按照UserJsonAdapter来执行。

     @JsonAdapter(UserJsonAdapter.class) public class User {  public final String firstName, lastName;  private User(String firstName, String lastName) {    this.firstName = firstName;    this.lastName = lastName; }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

JsonReader/JsonWriter

在Gson中,Java对象与JSON字符串之间的转换是通过字符流来进行操作的。JsonReader继承于Reader用来读取字符,JsonWriter继承于Writer用来写入字符。 
假如,现在有如下一段JSON数据用来表示一个用户列表。name为名字,age为年龄,geo为定位的经纬度。如何使用JsonReader转为java对象? 
image_1amg2niju16qh14gc1h3odm6k7q13.png-11.3kB 
首先查看一下json的结构,不难发现最外层是一个数组。于是,我们定义出如下readJsonStream从Stream(流)中读取用户列表,读取完毕后,务必记得关闭流。

//从流中读取List<User>public List<User> readJsonStream(InputStream in) throws IOException {     JsonReader reader = new JsonReader(new InputStreamReader(in, "UTF-8"));     try {       return readUserArray(reader);//读取用户列表     } finally {       reader.close();//关闭流     }   }//读取List<User>   public List<User> readUserArray(JsonReader reader) throws IOException {     List<User> users = new ArrayList<User>();     reader.beginArray();//开始读取数组     while (reader.hasNext()) {//是否还有下个元素       users.add(readUser(reader));//读取下个元素     }     reader.endArray();//结束读取数组     return users;   } //读取User对象  public User readUser(JsonReader reader) throws IOException {       String name = null;       int age = -1;       List<Double> geo=null;      reader.beginObject();//开始读取对象     while (reader.hasNext()) {//是否还有下个元素       String name = reader.nextName();//读取下一个json属性名        //判断属性名是哪一个       if (name.equals("name")) {           name = reader.nextString();       } else if (name.equals("age")) {           age = reader.nextInt();       } else if (name.equals("geo")&& reader.peek() != JsonToken.NULL) {          geo = readDoublesArray(reader);       } else {         reader.skipValue();//忽略没有匹配到内容的值       }     }     reader.endObject();//结束读取对象     return new User(name, age,geo);   }   //读取经纬度   public List<Double> readDoublesArray(JsonReader reader) throws IOException {     List<Double> doubles = new ArrayList<Double>();     reader.beginArray();     while (reader.hasNext()) {       doubles.add(reader.nextDouble());     }     reader.endArray();     return doubles;   }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

我们不难发现如下规律,每次读取数组或者对象之前,都必须调用beginObject()或者beginArray(),读完相应内容后,也必须调用endObject()或者endArray()reader.hasNext()用来判断是否还有下一个元素,然后调用nextName来取下一个属性名,以及一系列的nextXXX来取相应的值。 
上面介绍的是将json字符串转换为java对象的用法,现在来看看如何使用JsonWriter来讲java对象转为json字符串。

   //将List<User>写入流中   public void writeJsonStream(OutputStream out, List<User> users) throws IOException {     JsonWriter writer = new JsonWriter(new OutputStreamWriter(out, "UTF-8"));     writer.setIndent("    ");//设置缩进风格(设置后写入的字符串保持缩进风格,如果没有设置,将会顶格打印)     writeUsersArray(writer, users);//写入List<User>     writer.close();   }  //写入List<User>   public void writeUsersArray(JsonWriter writer, List<User> users) throws IOException {     writer.beginArray();//开始写入数组     for (User user : users) {       writeUser(writer, user);     }     writer.endArray();//结束写入数组   }   //写入User   public void writeUser(JsonWriter writer, User user) throws IOException {     writer.beginObject();//开始写入对象     writer.name("name").value(user.getName());     writer.name("age").value(user.getAge());     if (user.getGeo() != null) {       writer.name("geo");       writeDoublesArray(writer, user.getGeo());     } else {       writer.name("geo").nullValue();     }     writer.endObject();//结束写入对象   }   public void writeDoublesArray(JsonWriter writer, List<Double> doubles) throws IOException {     writer.beginArray();     for (Double value : doubles) {       writer.value(value);     }     writer.endArray();   }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

JsonWriter用来写入JSON字符串的规则和JsonWriter大相径庭,每次写入数组或者对象之前,都必须调用beginObject()或者beginArray(),写完相应内容后,也必须调用endObject()或者endArray()name(xx)用来写入名字,value(XX)用来写入值。 
接下来,深入浅出解析源码!stream包的结构如下: 
image_1amldac2a1qe33br1n9chm1n4s9.png-8.6kB 
枚举类JsonToken的源码如下,主要用于表示JSON字符串中的名字/值的结构。

public enum JsonToken {  BEGIN_ARRAY,//JSON array开始  END_ARRAY,//JSON array结束  BEGIN_OBJECT,//JSON object开始  END_OBJECT,//JSON object结束  NAME,//JSON 属性名,JsonReader#nextName/JsonWriter#name  STRING,//JSON 字符串  NUMBER,//JSON 数字,代表java中double,long,int  BOOLEAN,//JSON 布尔值  NULL, //表示 null  END_DOCUMENT //表示JSON流的结尾}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

JsonScope是一个常量类,元素词法作用域。用来标识JsonReader/JsonWriter现在读/写到哪了。

final class JsonScope {    static final int EMPTY_ARRAY = 1;//没有元素的数组(相当于之前刚读了“[”),下一个元素一定不是逗号。    static final int NONEMPTY_ARRAY = 2;//非空数组(至少已经有一个元素),下一个元素不是逗号就是“]”    static final int EMPTY_OBJECT = 3;//空对象(刚读到“{”,一个name/value对都没有),下一个一定不是逗号。    static final int DANGLING_NAME = 4;//名字,下一个元素一定是值。    static final int NONEMPTY_OBJECT = 5;//非空对象(至少一个name/value对),下一个元素不是逗号就是“}”    static final int EMPTY_DOCUMENT = 6;//空文档,初识状态,啥也没读    static final int NONEMPTY_DOCUMENT = 7;//文档中有一个顶级的数组/对象    static final int CLOSED = 8;//文档已被关闭}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

JsonWriter

JsonWriter,用于将Java对象写为JSON字符串。使用前我们可以进行一些默认的配置:

  //设置缩进符号,只要你设置了缩进符号,打印出来的字符串将会拥有缩进风格,非常漂亮  public final void setIndent(String indent)  //设置宽松的容错性(顶级值可以不是为object/array,数字可以为无穷)  public final void setLenient(boolean lenient)  //html转义  public final void setHtmlSafe(boolean htmlSafe)  //序列化空,默认true  public final void setSerializeNulls(boolean serializeNulls) 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

JsonWriter使用一个数组来保存当前的写入状态(就是标识写到哪了),JsonScope中已经介绍过了。

  private int[] stack = new int[32];  private int stackSize = 0;  {    push(EMPTY_DOCUMENT);  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

注意stack并没有定死32的长度,当写满时将会扩大一倍。使用push来保存当前写入状态,peek查看当前状态。

  //将当前状态保存栈顶  private void push(int newTop) {    if (stackSize == stack.length) {//如果满了就扩大一倍      int[] newStack = new int[stackSize * 2];      System.arraycopy(stack, 0, newStack, 0, stackSize);      stack = newStack;    }    stack[stackSize++] = newTop;  }  //查看栈顶的值  private int peek() {    if (stackSize == 0) {      throw new IllegalStateException("JsonWriter is closed.");    }    return stack[stackSize - 1];  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在写一个对象之前,必须使用beginObject()。一定很好奇beginObject()做了什么,当时还不忙着看,先来看看怎么写入name/value的。 
name(XX)源码如下:

  public JsonWriter name(String name) throws IOException {    if (name == null) {      throw new NullPointerException("name == null");    }    if (deferredName != null) {      throw new IllegalStateException();    }    if (stackSize == 0) {      throw new IllegalStateException("JsonWriter is closed.");    }    deferredName = name;//赋值给deferredName    return this;  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

看完源码不由觉得有点失望,只是赋值给了deferredName,其他什么事也没做。那么到底什么时候写入name的。这还得从写入value看起。 
value(XX)有很多重载函数。 
image_1amlgoj7n7bv1s5u13f8cv2baqm.png-9.9kB 
我们只看value(String)这种。

  public JsonWriter value(String value) throws IOException {    if (value == null) {//如果空的话,写入空值      return nullValue();    }    writeDeferredName();//写入name。    beforeValue();//写入“:”(会对上次状态进行校验)    string(value);//写入value(会对特殊字符进行转码)    return this;  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

通过writeDeferredName写入名字,beforeValue写入:,string写入真正的值。当然writeDeferredName也不是说直接写入name,而是先beforeName进行状态校验,换行,替换状态,按需写入,,然后使用string写入name值。

  private void writeDeferredName() throws IOException {    if (deferredName != null) {      beforeName();//校验等      string(deferredName);//写入名字      deferredName = null;    }  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

现在来看看beginObject,如果该对象是name/value中的value,那么writeDeferredName用来写入name。open写入{以及更改栈顶状态。

    public JsonWriter beginObject() throws IOException {    writeDeferredName();//写入name(如果有)    return open(EMPTY_OBJECT, "{"); //写入“{”  }
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

endObject则是调用close来写入},传入的EMPTY_OBJECT,EMPTY_OBJECT用来比较是在哪种状态下进行关闭的。

  public JsonWriter endObject() throws IOException {    return close(EMPTY_OBJECT, EMPTY_OBJECT, "}");  }
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

至于beginArray/endArray的源码这里就不赘述了。

JsonReader

JsonReader,用于将JSON字符串转为Java对象。 
JsonReader中的setLenient的容错性那可是非常厉害。以下错误都能被忽略。

  • )]}'\n 前缀
  • 多个顶级值
  • 顶级值不是 object/array类型
  • 数字类型为无穷数,或者不是个数字
  • 一行的结尾存在//或者 #注释
  • C语言风格的注释//
  • name用了单引号或者没用引号
  • string用了单引号或者没用引号
  • 数组元素的分隔符用了;而不是,
  • name和value不是用:分隔,而是用=或=>
  • name/value对之间不是逗号分隔,而是;分隔

和JsonWriter一样,也使用一个数组stack来保存当前的读取到的字符的类型和状态。其中引入了一系列的PEEKED_XXint常量来记录读取的字符类型。由于篇幅问题,JsonReader就不深入研究了,以下列出JsonReader中的核心方法。

  • fillBuffer 用来读取字符到buffer数组中
  • nextNonWhitespace 用来读取非空格/注释/换行等字符
  • peek() 查看元素类型,对应于JsonToken中的值。
  • doPeek() 内部使用了nextNonWhitespace读取一个字符,然后设置当前的读取的字符类型。
  • hasNext object/array中是不是还有下一个元素
  • nextName读取下一个name
  • nextString/nextInt/nextBoolean/nextLong/nextDouble/nextNull用来读取下一个对应的值。
  • skipValue 跳过下一个value
  • nextQuotedValue/nextUnquotedValue用来读取下一个单引号/双引号没有引号括起来的name或者string value
  • beginObject/endObject/beginArray/endArray 用来消费下一个对应类型的字符

Gson中的泛型

在了解Gson中的泛型前,我们来看两个类,$Gson$Types和$Gson$Preconditions。 
$Gson$Types,专门用来处理泛型类型。核心源码如下:

  //规范化类型  public static Type canonicalize(Type type) {    if (type instanceof Class) {//class      Class<?> c = (Class<?>) type;      return c.isArray() ? new GenericArrayTypeImpl(canonicalize(c.getComponentType())) : c;    } else if (type instanceof ParameterizedType) {//泛型      ParameterizedType p = (ParameterizedType) type;      return new ParameterizedTypeImpl(p.getOwnerType(),          p.getRawType(), p.getActualTypeArguments());    } else if (type instanceof GenericArrayType) {//数组类型      GenericArrayType g = (GenericArrayType) type;      return new GenericArrayTypeImpl(g.getGenericComponentType());    } else if (type instanceof WildcardType) {//通配符类型      WildcardType w = (WildcardType) type;      return new WildcardTypeImpl(w.getUpperBounds(), w.getLowerBounds());    } else {      // type is either serializable as-is or unsupported      return type;    }  }  //获取原始类型    public static Class<?> getRawType(Type type) {    if (type instanceof Class<?>) {      return (Class<?>) type;    } else if (type instanceof ParameterizedType) {      //泛型      ParameterizedType parameterizedType = (ParameterizedType) type;      Type rawType = parameterizedType.getRawType();      checkArgument(rawType instanceof Class);      return (Class<?>) rawType;    } else if (type instanceof GenericArrayType) {      //数组类型      Type componentType = ((GenericArrayType)type).getGenericComponentType();      return Array.newInstance(getRawType(componentType), 0).getClass();    } else if (type instanceof TypeVariable) {           //类型变量的上边界是Object           return Object.class;    } else if (type instanceof WildcardType) {       //返回上边界      return getRawType(((WildcardType) type).getUpperBounds()[0]);    } else {      String className = type == null ? "null" : type.getClass().getName();      throw new IllegalArgumentException("Expected a Class, ParameterizedType, or "          + "GenericArrayType, but <" + type + "> is of type " + className);    }  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

canonicalize这个方法中返回了一系列的XXImpl,其实只是实现了java.io.Serializable接口,重写了equal方法而已。其中ParameterizedType/GenericArrayType/WildcardType,熟悉泛型的应该不会陌生,这里就不赘述了。

$Gson$Preconditions,这个类用于条件校验,源码很是简洁。

public final class $Gson$Preconditions {  private $Gson$Preconditions() {    throw new UnsupportedOperationException();  }  public static <T> T checkNotNull(T obj) {//校验非空    if (obj == null) {      throw new NullPointerException();    }    return obj;  }  public static void checkArgument(boolean condition) {//校验是不是满足条件    if (!condition) {      throw new IllegalArgumentException();    }  }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

现在回过来了解Gson中的泛型,Gson中用TypeToken来表示泛型。 
源码如下:

public class TypeToken<T> {  final Class<? super T> rawType;//T的原始类型  final Type type; //T 的类型  final int hashCode;  protected TypeToken() {   //获取父类泛型的参数类型    this.type = getSuperclassTypeParameter(getClass());    //获取原始类型    this.rawType = (Class<? super T>) $Gson$Types.getRawType(type);    this.hashCode = type.hashCode();  }   public final Class<? super T> getRawType() {    return rawType;  }  public final Type getType() {    return type;  }  //..  //省略了部分源码  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

由于Java中只能通过getGenericSuperclass获取父类泛型类型,所以TypeToken必须new出一个子类Type type= new TypeToken<List<User>>(){}.getType();来使用。 
getSuperclassTypeParameter的源码如下:

  static Type getSuperclassTypeParameter(Class<?> subclass) {    Type superclass = subclass.getGenericSuperclass();//获取父类泛型类型    if (superclass instanceof Class) {      throw new RuntimeException("Missing type parameter.");    }    ParameterizedType parameterized = (ParameterizedType) superclass;    //获取泛型参数类型,即T的类型    return $Gson$Types.canonicalize(parameterized.getActualTypeArguments()[0]);  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

JsonElement

JsonElement,一个抽象类,代表着JSON中的元素类型。可以表示JsonObject,JsonArray,JsonPrimitive,JsonNull。换言之,Gson中的JsonObject/JsonArray/JsonPrimitive/JsonNull继承于JsonElement。JsonElement也提供了一系列的getAsXXX方法来获取元素。 
我们着重看一下JsonPrimitive,JsonPrimitive代表着java中的基本数据类型。可以看出,通过构造方法进行赋值,然后通过getAsXX取值。

public final class JsonPrimitive extends JsonElement {//基本类型列表如下  private static final Class<?>[] PRIMITIVE_TYPES = { int.class, long.class, short.class,      float.class, double.class, byte.class, boolean.class, char.class, Integer.class, Long.class,      Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class };  //值  private Object value;    public JsonPrimitive(Boolean bool) {    setValue(bool);  }  //赋值数字类型  public JsonPrimitive(Number number) {    setValue(number);  } //赋值String  public JsonPrimitive(String string) {    setValue(string);  }  //赋值字符  public JsonPrimitive(Character c) {    setValue(c);  }  //赋值给valuevoid setValue(Object primitive) {    if (primitive instanceof Character) {      char c = ((Character) primitive).charValue();      this.value = String.valueOf(c);    } else {      $Gson$Preconditions.checkArgument(primitive instanceof Number              || isPrimitiveOrString(primitive));      this.value = primitive;    }  }  //..  //省略了部分源码  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

Gson中的TypeAdapter

还记得介绍注解时提到的TypeAdapter吗?TypeAdapter是一个抽象类,可以用来自定义类型转换。源码如下。

public abstract class TypeAdapter<T> {  //抽象方法,写value(an array, object, string, number, boolean or null)  public abstract void write(JsonWriter out, T value) throws IOException; //抽象方法,读value  public abstract T read(JsonReader in) throws IOException;  //包装方法,帮你处理了空值,你可以不用担心空值问题  public final TypeAdapter<T> nullSafe() {    return new TypeAdapter<T>() {      @Override public void write(JsonWriter out, T value) throws IOException {        if (value == null) {//如果为空,写入null          out.nullValue();        } else {          TypeAdapter.this.write(out, value);        }      }      @Override public T read(JsonReader reader) throws IOException {        if (reader.peek() == JsonToken.NULL) {          reader.nextNull();          return null;        }        return TypeAdapter.this.read(reader);      }    };  }  //..  //省略了部分源码}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

我们只需继承于TypeAdapter,实现相应方法就能实现自己的TypeAdapter,前面我们介绍了使用注解方法来使用TypeAdapter,现在来讲一下在GsonBuilder中如何使用。

  Gson gson= new GsonBuilder()                .registerTypeAdapter(XX.class,new XXTypeAdapter())                .create();
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

在GsonBuilder中使用registerTypeAdapter配置后,就不需要使用相关注解了。那么问题来了,如果GsonBuilder和注解为同一个类配置了不同的TypeAdapter会发生什么状况?我可以很负责任的告诉你,注解的优先级是最高的。 
此外,我们之前在编写UserJsonAdapter时没有处理空值情况,很容易会抛出异常,那怎么办?一种是自己处理空值情况,将代码改成如下形式。

public class UserJsonAdapter extends TypeAdapter<User> {@Override public void write(JsonWriter out, User user) throws IOException {if (user == null) {//判断空值    out.nullValue();    retrun;  } out.beginObject(); out.name("name"); out.value(user.firstName + " " + user.lastName); out.endObject();}@Override public User read(JsonReader in) throws IOException { if (reader.peek() == JsonToken.NULL) {//判断空值         reader.nextNull();         return null;    } in.beginObject(); in.nextName(); String[] nameParts = in.nextString().split(" "); in.endObject(); return new User(nameParts[0], nameParts[1]);}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

第二种方法,使用nullSafe:

 Gson gson= new GsonBuilder()                .registerTypeAdapter(User.class,new UserJsonAdapter().nullSafe())                .create();
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

TypeAdapterFactory是一个创造TypeAdapter的工厂,用来创造一些相似类型的TypeAdapter。

public interface TypeAdapterFactory {  <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type);}
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

继承TypeAdapter,需要重写writeread相关方法,可是只想处理序列化和反序列化中的一种该怎么办?那么接下来就该介绍JsonSerializerJsonDeserializer接口了。可以在@JsonAdapter注解和registerTypeAdapter中注册使用。

//序列化public interface JsonSerializer<T> {  public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context);}//反序列化public interface JsonDeserializer<T> {  public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)throws JsonParseException;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

序列化策略

  • LongSerializationPolicy 
    枚举类,指定长整型的序列化类型,默认有DEFAULT,STRING两种类型,可继承它实现其他类型

  • InstanceCreator 实例创造器 
    当反序列化时需要实例化对象,但是假如该对象没有默认构造方法怎么吧?那么就自定义自己的实例创造器。InstanceCreator一般配合ConstructorConstructor一起使用。

    public interface InstanceCreator<T> {public T createInstance(Type type);}
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4
    class UserInstanceCreator implements InstanceCreator<User> {public User createInstance(Type type) {  return new User(null, -1);}}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5
  • FieldNamingStrategy 
    提供了一个自定义的字段命名机制

    public interface FieldNamingStrategy {public String translateName(Field f);}
    • 1
    • 2
    • 3
    • 4
    • 1
    • 2
    • 3
    • 4
  • FieldNamingPolicy 
    一个枚举类,实现了FieldNamingStrategy,提供了一些默认的字段命名机制,IDENTITY:原始机制;UPPER_CAMEL_CASE:首字母大写的驼峰映射;UPPER_CAMEL_CASE_WITH_SPACES:用空格分隔的大写驼峰LOWER_CASE_WITH_UNDERSCORES:下划线相连的小写映射;LOWER_CASE_WITH_DASHES:虚线相连的小写映射。

  • FieldAttributes 
    用来存取字段的属性:getName获取字段名,getDeclaringClass获取声明的类,getDeclaredType获取字段的声明类型,getAnnotation获取注解。

  • ExclusionStrategy 
    一个用于定义排除策略的的接口。

    public interface ExclusionStrategy {//是否应该忽略该属性public boolean shouldSkipField(FieldAttributes f);//是否应该忽略该类public boolean shouldSkipClass(Class<?> clazz);}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

其他

  • Excluder 排除器,主要用于根据策略和注解来判断哪些字段应该被忽略。 
    属性如下:

    private static final double IGNORE_VERSIONS = -1.0d;public static final Excluder DEFAULT = new Excluder();//默认忽略版本号private double version = IGNORE_VERSIONS;//默认以下修饰符的字段会被忽略private int modifiers = Modifier.TRANSIENT | Modifier.STATIC;private boolean serializeInnerClasses = true;//序列化内部类private boolean requireExpose;//需要Expose注解?//存放序列化排除策略private List<ExclusionStrategy> serializationStrategies = Collections.emptyList();//存放反序列化排除策略private List<ExclusionStrategy> deserializationStrategies = Collections.emptyList();
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    所有的方法如下: 
    image_1amm2a5vkurd1t6ku4412do8om9.png-45.5kB

  • Primitives 一个工具类,用于在原始类型和包装类型间转化。wrap包装,unwrap解开。

  • ObjectConstructor 一个人通用的构造器接口。

    public interface ObjectConstructor<T> {  public T construct();}
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3
  • ConstructorConstructor 保存实例构造器集合的类

    public final class ConstructorConstructor { //实例创造器集合 private final Map<Type, InstanceCreator<?>> instanceCreators; //通过类型返回一个构造器public <T> ObjectConstructor<T> get(TypeToken<T> typeToken) {final Type type = typeToken.getType();//获取类型final Class<? super T> rawType = typeToken.getRawType();//获取真实类型//首先从集合中获取看有没有相同的Type,有就创造实例并返回final InstanceCreator<T> typeCreator = (InstanceCreator<T>) instanceCreators.get(type);if (typeCreator != null) {  return new ObjectConstructor<T>() {    @Override public T construct() {      return typeCreator.createInstance(type);    }  };}//然后根据原始类型取,去集合中取final InstanceCreator<T> rawTypeCreator =    (InstanceCreator<T>) instanceCreators.get(rawType);if (rawTypeCreator != null) {  return new ObjectConstructor<T>() {    @Override public T construct() {      return rawTypeCreator.createInstance(type);    }  };}//获取默认构造方法ObjectConstructor<T> defaultConstructor = newDefaultConstructor(rawType);if (defaultConstructor != null) {  return defaultConstructor;}//获取集合类型的构造器(Collection,EnumSet,Set,Queue,Map)ObjectConstructor<T> defaultImplementation = newDefaultImplementationConstructor(type, rawType);if (defaultImplementation != null) {  return defaultImplementation;}// 使用不安全的分配器return newUnsafeAllocator(type, rawType);} //.. //省略了部分源码 }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
  • JsonStreamParser 解析器,解析为JsonElement。hasNext:是否有下一个元素,next取下一个元素,返回JsonElement。

  • Streams 内部使用TypeAdapters.JSON_ELEMENT写入/读取下一个JsonElement。

GSON 源码解读

构造方法

现在我们从Gson的构造方法入手,解读Gson是如何工作的。

 Gson(final Excluder excluder, final FieldNamingStrategy fieldNamingStrategy,      final Map<Type, InstanceCreator<?>> instanceCreators, boolean serializeNulls,      boolean complexMapKeySerialization, boolean generateNonExecutableGson, boolean htmlSafe,      boolean prettyPrinting, boolean lenient, boolean serializeSpecialFloatingPointValues,      LongSerializationPolicy longSerializationPolicy,      List<TypeAdapterFactory> typeAdapterFactories) {    this.constructorConstructor = new ConstructorConstructor(instanceCreators);//实例构造器    this.excluder = excluder;//排除器    this.fieldNamingStrategy = fieldNamingStrategy;//字段命名策略    this.serializeNulls = serializeNulls;//序列化空    this.generateNonExecutableJson = generateNonExecutableGson;//生成不可执行前缀(用来防止攻击)    this.htmlSafe = htmlSafe;//html转义    this.prettyPrinting = prettyPrinting;//缩进打印    this.lenient = lenient;//宽松的容错性    List<TypeAdapterFactory> factories = new ArrayList<TypeAdapterFactory>();//TypeAdapter的工厂列表    //以下都是往工厂列表加入TypeAdapterFactory    // 构建不能被重载的TypeAdapter    factories.add(TypeAdapters.JSON_ELEMENT_FACTORY);    factories.add(ObjectTypeAdapter.FACTORY);    // 排除器必须在所有的用于自定义的typeAdapter之前    factories.add(excluder);    //用户自定义的typeAdapter工厂    factories.addAll(typeAdapterFactories);    //以下为默认的TypeAdapter    factories.add(TypeAdapters.STRING_FACTORY);    factories.add(TypeAdapters.INTEGER_FACTORY);    factories.add(TypeAdapters.BOOLEAN_FACTORY);    factories.add(TypeAdapters.BYTE_FACTORY);    factories.add(TypeAdapters.SHORT_FACTORY);    TypeAdapter<Number> longAdapter = longAdapter(longSerializationPolicy);    factories.add(TypeAdapters.newFactory(long.class, Long.class, longAdapter));    factories.add(TypeAdapters.newFactory(double.class, Double.class,            doubleAdapter(serializeSpecialFloatingPointValues)));    factories.add(TypeAdapters.newFactory(float.class, Float.class,            floatAdapter(serializeSpecialFloatingPointValues)));    factories.add(TypeAdapters.NUMBER_FACTORY);    factories.add(TypeAdapters.ATOMIC_INTEGER_FACTORY);    factories.add(TypeAdapters.ATOMIC_BOOLEAN_FACTORY);    factories.add(TypeAdapters.newFactory(AtomicLong.class, atomicLongAdapter(longAdapter)));    factories.add(TypeAdapters.newFactory(AtomicLongArray.class, atomicLongArrayAdapter(longAdapter)));    factories.add(TypeAdapters.ATOMIC_INTEGER_ARRAY_FACTORY);    factories.add(TypeAdapters.CHARACTER_FACTORY);    factories.add(TypeAdapters.STRING_BUILDER_FACTORY);    factories.add(TypeAdapters.STRING_BUFFER_FACTORY);    factories.add(TypeAdapters.newFactory(BigDecimal.class, TypeAdapters.BIG_DECIMAL));    factories.add(TypeAdapters.newFactory(BigInteger.class, TypeAdapters.BIG_INTEGER));    factories.add(TypeAdapters.URL_FACTORY);    factories.add(TypeAdapters.URI_FACTORY);    factories.add(TypeAdapters.UUID_FACTORY);    factories.add(TypeAdapters.CURRENCY_FACTORY);    factories.add(TypeAdapters.LOCALE_FACTORY);    factories.add(TypeAdapters.INET_ADDRESS_FACTORY);    factories.add(TypeAdapters.BIT_SET_FACTORY);    factories.add(DateTypeAdapter.FACTORY);    factories.add(TypeAdapters.CALENDAR_FACTORY);    factories.add(TimeTypeAdapter.FACTORY);    factories.add(SqlDateTypeAdapter.FACTORY);    factories.add(TypeAdapters.TIMESTAMP_FACTORY);    factories.add(ArrayTypeAdapter.FACTORY);    factories.add(TypeAdapters.CLASS_FACTORY);    //复合的TypeAdapter    factories.add(new CollectionTypeAdapterFactory(constructorConstructor));    factories.add(new MapTypeAdapterFactory(constructorConstructor, complexMapKeySerialization));    this.jsonAdapterFactory = new JsonAdapterAnnotationTypeAdapterFactory(constructorConstructor);    factories.add(jsonAdapterFactory);    factories.add(TypeAdapters.ENUM_FACTORY);    factories.add(new ReflectiveTypeAdapterFactory(        constructorConstructor, fieldNamingStrategy, excluder, jsonAdapterFactory));    this.factories = Collections.unmodifiableList(factories);  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83

构造方法让人看的眼花缭乱,尤其是往集合中加入了那么多的TypeAdapterFactory。由于是在太多无法逐一介绍。就挑个最简单的来讲解。总之明白TypeAdapter的作用即可。 
ObjectTypeAdapter:内部有一个静态工厂类,所以只需ObjectTypeAdapter.FACTORY这样调用即可。

public final class ObjectTypeAdapter extends TypeAdapter<Object> {  //工厂类  public static final TypeAdapterFactory FACTORY = new TypeAdapterFactory() {    //该工厂用来创建Object类型的TypeAdapter    @Override public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {      if (type.getRawType() == Object.class) {        return (TypeAdapter<T>) new ObjectTypeAdapter(gson);      }      return null;    }  };
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

接口的实现方法如下:

//读取 @Override public Object read(JsonReader in) throws IOException {    JsonToken token = in.peek();//查看元素类型    switch (token) {    case BEGIN_ARRAY://数组      List<Object> list = new ArrayList<Object>();      in.beginArray();//开始标识      while (in.hasNext()) {//还有下一个元素?        list.add(read(in));      }      in.endArray();//结束标识      return list;    case BEGIN_OBJECT://对象      Map<String, Object> map = new LinkedTreeMap<String, Object>();      in.beginObject();      while (in.hasNext()) {        map.put(in.nextName(), read(in));      }      in.endObject();      return map;    case STRING:      return in.nextString();    case NUMBER:      return in.nextDouble();    case BOOLEAN:      return in.nextBoolean();    case NULL:      in.nextNull();      return null;    default:      throw new IllegalStateException();    }  }  //写为json  @Override public void write(JsonWriter out, Object value) throws IOException {    if (value == null) {      out.nullValue();      return;    }    //gson.getAdapter获取对应类型的TypeAdapter    TypeAdapter<Object> typeAdapter = (TypeAdapter<Object>) gson.getAdapter(value.getClass());    if (typeAdapter instanceof ObjectTypeAdapter) {      out.beginObject();      out.endObject();      return;    }    typeAdapter.write(out, value);  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56

关于TypeAdapter这里就不继续深究了,预定义的TypeAdapter实在太多了。其中JsonAdapterAnnotationTypeAdapterFactory用来处理@JsonAdapter注解,ReflectiveTypeAdapterFactory用来反射获取字段等等。

getAdapter

将Java对象序列化为Json字符串时,需要调用gson.getAdapter(XX)来获取相应类型的转换器,然后按照TypeAdapter中规定好的规则进行序列化/反序列化。

 public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {    //从typeTokenCache的Map中取出    //NULL_KEY_SURROGATE表示Object类型    TypeAdapter<?> cached = typeTokenCache.get(type == null ? NULL_KEY_SURROGATE : type);    if (cached != null) {      return (TypeAdapter<T>) cached;    }   //threadCalls是一个中间线程变量    Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();    boolean requiresThreadLocalCleanup = false;    if (threadCalls == null) {      threadCalls = new HashMap<TypeToken<?>, FutureTypeAdapter<?>>();      calls.set(threadCalls);      requiresThreadLocalCleanup = true;    }     //取回FutureTypeAdapter,FutureTypeAdapter是一个代理TypeAdapter    FutureTypeAdapter<T> ongoingCall = (FutureTypeAdapter<T>) threadCalls.get(type);    if (ongoingCall != null) {      return ongoingCall;    }    try {    //new FutureTypeAdapter      FutureTypeAdapter<T> call = new FutureTypeAdapter<T>();      threadCalls.put(type, call);//放入线程变量中     //从工厂中遍历,加入typeTokenCache      for (TypeAdapterFactory factory : factories) {        TypeAdapter<T> candidate = factory.create(this, type);//create创造实例        if (candidate != null) {          call.setDelegate(candidate);          typeTokenCache.put(type, candidate);          return candidate;        }      }      throw new IllegalArgumentException("GSON cannot handle " + type);    } finally {      threadCalls.remove(type);      if (requiresThreadLocalCleanup) {        calls.remove();      }    }  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

以上源码的流程是这样的。首先从typeTokenCache中获取看看有没有相应类型的Adapter,第一次肯定没有,然后利用中间变量FutureTypeAdapter,从工厂中遍历去取,然后放入typeTokenCache中。FutureTypeAdapter是一个代理TypeAdapter,内部还是原TypeAdapter进行处理。

toJson

终于快接近尾声了,现在来看toJson方法的内部原理,到底是怎么一步步将对象转为Json字符串的。最终调用的是toJson(Object src, Type typeOfSrc, JsonWriter writer)方法,通过相应的Adapter进行读写。

  //传入一个Object  public String toJson(Object src) {    if (src == null) {      return toJson(JsonNull.INSTANCE);    }    return toJson(src, src.getClass());//重载调用  }  //重载方法  public String toJson(Object src, Type typeOfSrc) {    StringWriter writer = new StringWriter();    toJson(src, typeOfSrc, writer);    return writer.toString();//返回String  }//将StringWriter转为JsonWriter。public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {    try {      JsonWriter jsonWriter = newJsonWriter(Streams.writerForAppendable(writer));//转为JsonWriter。      toJson(src, typeOfSrc, jsonWriter);    } catch (IOException e) {      throw new JsonIOException(e);    }  }  public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {    //调用getAdapter获取相应类型的TypeAdapter。    TypeAdapter<?> adapter = getAdapter(TypeToken.get(typeOfSrc));    //设置配置    boolean oldLenient = writer.isLenient();    writer.setLenient(true);    boolean oldHtmlSafe = writer.isHtmlSafe();    writer.setHtmlSafe(htmlSafe);    boolean oldSerializeNulls = writer.getSerializeNulls();    writer.setSerializeNulls(serializeNulls);    try {      //调用adapter的write方法      ((TypeAdapter<Object>) adapter).write(writer, src);    } catch (IOException e) {      throw new JsonIOException(e);    } finally {      writer.setLenient(oldLenient);      writer.setHtmlSafe(oldHtmlSafe);      writer.setSerializeNulls(oldSerializeNulls);    }  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48

fromJson

  //传入一个json字符串和一个转换类型。  public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {    Object object = fromJson(json, (Type) classOfT);//调用重载    return Primitives.wrap(classOfT).cast(object);//如果是基本数据类型还会被包装返回(即 int => Integer)  } //重载方法     public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {    if (json == null) {      return null;    }    StringReader reader = new StringReader(json);//使用StringReader包装    T target = (T) fromJson(reader, typeOfT);    return target;  }  //重载方法,将StringReader转为JsonReader  public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {    JsonReader jsonReader = newJsonReader(json);    T object = (T) fromJson(jsonReader, typeOfT);    assertFullConsumption(object, jsonReader);//判断是不是读完了    return object;  } //最终方法 public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {    boolean isEmpty = true;    boolean oldLenient = reader.isLenient();    reader.setLenient(true);    try {      reader.peek();      isEmpty = false;      //转为TypeToken      TypeToken<T> typeToken = (TypeToken<T>) TypeToken.get(typeOfT);      //获取TypeAdapter      TypeAdapter<T> typeAdapter = getAdapter(typeToken);      //调用TypeAdapter的read      T object = typeAdapter.read(reader);      return object;    } catch (EOFException e) {     //..     //省略部分源码    } finally {      reader.setLenient(oldLenient);    }  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

GsonBuilder

GsonBuilder用来对Gson进行配置,比如注册TypeAdapter等等。最后调用create()返回Gson对象。 
image_1amn76ilalcs2usk3t1mjddmm9.png-55.7kB

最后

Gson内部的Json与Java间的转换依赖于各类的TypeAdapter,通过registerTypeAdapter可以注册新的类型转换器,实例创造器的等。越先注册的优先级就越高。当然,如果你没有注册Adapter,对于自定义的对象一般参与转换的Adapter是ReflectiveTypeAdapterFactory。有兴趣的请自行阅读源码。 
registerTypeAdapter的源码如下:

  public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {   //校验参数    $Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>        || typeAdapter instanceof JsonDeserializer<?>        || typeAdapter instanceof InstanceCreator<?>        || typeAdapter instanceof TypeAdapter<?>);     //实例构造器       if (typeAdapter instanceof InstanceCreator<?>) {      instanceCreators.put(type, (InstanceCreator) typeAdapter);    }    //序列化/反序列化    if (typeAdapter instanceof JsonSerializer<?> || typeAdapter instanceof JsonDeserializer<?>) {      TypeToken<?> typeToken = TypeToken.get(type);      factories.add(TreeTypeAdapter.newFactoryWithMatchRawType(typeToken, typeAdapter));    }    //TypeAdapter    if (typeAdapter instanceof TypeAdapter<?>) {      factories.add(TypeAdapters.newFactory(TypeToken.get(type), (TypeAdapter)typeAdapter));    }    return this;  }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

本期解读到此结束,由于篇幅问题,Gson中预定义的TypeAdapter实在太多就不进行分析了。