Gson源碼分析之Json結構抽象和註解使用

github上的博客地址:
http://chuyun923.github.io/blog/2015/01/06/gsonyuan-ma-fen-xi/java

XML和Json做爲最經常使用的兩種網絡傳輸格式而被普遍使用,XML在早期數據傳輸中做爲首選,可是近年來Json以其輕量級和更容易編寫和解析而愈來愈流行,Gson做爲google的一個開源Json解析框架提供了穩定和快速解析的功能,能夠讀讀它的源代碼瞭解一番。
git

說到Gson,其實它無非就是作兩個工做,序列化(Object--->JsonString)和反序列化(JsonString--->Object),後文所說的兩個方向從Object到String和String到Object的兩個方向。可想而知,對於序列化來講,是較爲容易的工做,而對於反序列化即Json解析纔是Gson的重頭戲。既然是對Json字符串的解析,那麼少不了對Json字符串中的結構進行抽象。github

Json抽象類

JsonElement

這是Json中元素的基類,它只提供了若干個類型判斷的接口,簡單判斷這個Json元素的類型。如下幾個類型都是它的子類。json

一、JsonObject

包含多個JsonElement的集合,它在Json中對應這種類型的數據:後端

{
    "count":100,
    "users":[],
    "paging":{
        "offset":0,
        "limit":10,
        "hasMore":true
    }
}

這個data是一個典型的JsonObject,它以{開頭,其中包含了一些相似數值,數組,對象等其餘JsonElement的內容。其實每個Json字符串的根節點都是一個JsonObject。數組

JsonObject提供了比較多的方法來獲得Json中的信息,addProperty()函數能夠在當前Json節點下新建子結點。網絡

二、JsonArray

JsonArray也表示JsonElement的集合,注意:Json中的數組並不要求全部的數據類型都同樣框架

[true,"hello"] //JsonArray,包括一個boolean和一個hello類型。

須要討論的是JsonArray和JsonObject的區別是什麼?從集合的角度來講,JsonObject中的JsonElement是無序的,而JsonArray中的集合元素是有序的,從直觀感覺來講,你能夠經過下標來引用JsonArray中的元素,而JsonObject是經過鍵值對的方式來訪問的,get("name")--->value函數

三、JsonPrimitive

對應Json中的基本類型,好比boolean,int,固然提供了基本類型和包裝類的自動替換。jsonp

"count":100

四、JsonNull

空,對應null

"person":null

以上就是Gson對應Json結構的封裝。

註解-Annotations

Expose

在對象進行序列化和反序列化的過程當中,咱們能夠經過註解來屏蔽某一些字段。這個註解默認有兩個參數,serializedeserialize都是默認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()來實現。

未完

相關文章
相關標籤/搜索