github上的博客地址:
http://chuyun923.github.io/blog/2015/01/06/gsonyuan-ma-fen-xi/
XML和Json作為最常用的兩種網絡傳輸格式而被廣泛使用,XML在早期數據傳輸中作為首選,但是近年來Json以其輕量級和更容易編寫和解析而越來越流行,Gson作為google的一個開源Json解析框架提供了穩定和快速解析的功能,可以讀讀它的源代碼了解一番。
說到Gson,其實它無非就是做兩個工作,序列化(Object--->JsonString)和反序列化(JsonString--->Object),后文所說的兩個方向從Object到String和String到Object的兩個方向。可想而知,對於序列化來說,是較為容易的工作,而對於反序列化即Json解析才是Gson的重頭戲。既然是對Json字符串的解析,那么少不了對Json字符串中的結構進行抽象。
Json抽象類
JsonElement
這是Json中元素的基類,它只提供了若干個類型判斷的接口,簡單判斷這個Json元素的類型。以下幾個類型都是它的子類。
1、JsonObject
包含多個JsonElement的集合,它在Json中對應這種類型的數據:
{
"count":100,
"users":[],
"paging":{
"offset":0,
"limit":10,
"hasMore":true
}
}
這個data是一個典型的JsonObject,它以{開頭,其中包含了一些類似數值,數組,對象等其他JsonElement的內容。其實每一個Json字符串的根節點都是一個JsonObject。
JsonObject提供了比較多的方法來得到Json中的信息,addProperty()函數可以在當前Json節點下新建子結點。
2、JsonArray
JsonArray也表示JsonElement的集合,注意:Json中的數組並不要求所有的數據類型都一樣。
[true,"hello"] //JsonArray,包括一個boolean和一個hello類型。
需要討論的是JsonArray和JsonObject的區別是什么?從集合的角度來說,JsonObject中的JsonElement是無序的,而JsonArray中的集合元素是有序的,從直觀感受來說,你可以通過下標來引用JsonArray中的元素,而JsonObject是通過鍵值對的方式來訪問的,get("name")--->value。
3、JsonPrimitive
對應Json中的基本類型,比如boolean,int,當然提供了基本類型和包裝類的自動替換。
"count":100
4、JsonNull
空,對應null
"person":null
以上就是Gson對應Json結構的封裝。
注解-Annotations
Expose
在對象進行序列化和反序列化的過程中,我們可以通過注解來屏蔽某一些字段。這個注解默認有兩個參數,serialize和deserialize都是默認true。如果設置為false,表示這個序列化(反)的過程中,這一個屬性不需要進行處理。
通過Expose標注的屬性在直接new Gson()的情況下不能生效,我們必須通過Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create()來創建一個可以識別Expose注解的Gson。
小小的吐槽一把,這個地方的使用確實不太方便,舉個栗子,一般來說,我們進行序列化的時候都是希望某一個屬性不會序列化到Json字符里面(反之亦然),所以這里的一般思維是我要去處理這些特殊的屬性。而如果你想通過Expose來去掉10個屬性中的某一個,對不起,10個屬性你都需要加上@Expose,然后對你想要處理的那個屬性的Expose注解增加false參數,簡直就是坑爹。。。。
//我想讓Person類在序列化時,不去序列化password,是不是很坑爹?
class Person {
@Expose
private String userName;
@Expose (serialize = false)
private String passWord;
}
此外,和java本身的序列化一樣,如果一個屬性設置為transient或者static,那么兩個序列化的兩個方向上都會屏蔽掉這個屬性,雖然比Expose簡單,但是不夠靈活。
SerializedName
這個注解使用較多,它會改變兩個方向上這個屬性的名稱,在序列化是,JsonElement的鍵值會被替換成這個名字;解析時,Json中鍵值為這個名字的JsonElement會賦值給被注解的屬性。
class Person {
@SerializedName(value = "A")
private int a = 1;
private int b = 2;
}
//{"A":1,"b":2} 這個Json字符串和前面的Person等價
它使用場景最多的地方就是比如后端返回的json中的名稱和我們定義的model類名稱不一樣時使用。
Since 和 Until
我們可以對我們的Model類進行序列化(兩個方向)的版本控制,Since和Until剛好是兩個相反的意義。
例子:
class Person {
@Since(value = 1.0) //GsonBuilder指定版本要從1.0開始的Gson才能解析
private int a = 1;
@Until(value = 1.5) //GsonBuilder指定版本到1.5的Gson都可以解析,超過了不能解析
private int b = 2;
}
和Expose一樣,要想Gson識別這兩個注解,同樣需要通過GsonBuilder.setVersion(double).create()來實現。
未完
