日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

GSON使用筆記(3)

 王慶峰 2015-06-19

本文通過(guò)3個(gè)問(wèn)題來(lái)討論如何使用GSON把JSON反序列化為L(zhǎng)ist。

問(wèn)題1

有這樣兩個(gè)類(lèi):

  1. class MyObj {  
  2.     int x;  
  3. }  
  4.   
  5. class MyList {  
  6.     List<MyObj> objList = new LinkedList<>();  
  7. }  
那下面的測(cè)試能通過(guò)嗎?
  1. @Test  
  2. public void test1() {  
  3.     MyList myList = new Gson().fromJson("{objList:[]}", MyList.class);  
  4.     Assert.assertEquals(LinkedList.class, myList.objList.getClass());  
  5. }  

答案1

答案是,測(cè)試通不過(guò)!原因是GSON不知道objList的具體類(lèi)型,因此只能選擇默認(rèn)的ArrayList。更詳細(xì)的解釋?zhuān)梢詤⒖?a target="_blank" >這篇文章和ConstructorConstructor類(lèi)的源代碼。如果確實(shí)想讓GSON創(chuàng)建LinkedList實(shí)例該怎么辦呢?也簡(jiǎn)單,就是給objList一個(gè)更具體的類(lèi)型:

  1. class MyList {  
  2.     LinkedList<MyObj> objList = new LinkedList<>();  
  3. }  

問(wèn)題2

下面的測(cè)試能通過(guò)嗎?

  1. @Test  
  2. public void test2() {  
  3.     ArrayList<?> list = new Gson().fromJson("[{x:1}]", ArrayList.class);  
  4.     Assert.assertEquals(1, list.size());  
  5.     Assert.assertEquals(MyObj.class, list.get(0).getClass());  
  6. }  

答案2

很明顯,不能。因?yàn)閒romJson方法不能從"[{x:1}]"參數(shù)推測(cè)出數(shù)組里放的是MyObj類(lèi)型的對(duì)象,也無(wú)法從ArrayList.class參數(shù)得到這個(gè)信息。那么改成下面這樣呢?

  1. ArrayList<MyObj> list = new Gson().fromJson("[{x:1}]", ArrayList<MyObj>.class);  
更糟糕,連編譯都無(wú)法通過(guò)!因?yàn)镴ava的泛型是用擦拭法實(shí)現(xiàn)的,說(shuō)白了只是編譯器提供給程序員的語(yǔ)法糖,根本不存在ArrayList<MyObj>這樣一個(gè)類(lèi)。那么怎樣才能讓GSON反序列化出我們想要的泛型對(duì)象呢?答案是,請(qǐng)TypeToken幫忙:
  1. @Test  
  2. public void test3() {  
  3.     Type type = new TypeToken<ArrayList<MyObj>>() {}.getType();  
  4.     ArrayList<MyObj> list = new Gson().fromJson("[{x:1}]", type);  
  5.     Assert.assertEquals(1, list.size());  
  6.     Assert.assertEquals(MyObj.class, list.get(0).getClass());  
  7. }  
GSON提供了TypeToken這個(gè)類(lèi)來(lái)幫助我們捕獲(capture)像ArrayList<MyObj>這樣的泛型信息。test3()的第一行代碼創(chuàng)建了一個(gè)匿名內(nèi)部類(lèi),這樣,Java編譯器就會(huì)把泛型信息編譯到這個(gè)匿名內(nèi)部類(lèi)里,然后在運(yùn)行時(shí)就可以被getType()方法用反射API提取到。

問(wèn)題3

如果我想寫(xiě)一個(gè)通用的方法,把json反序列化成List,下面這個(gè)方法可行嗎?

  1. public static <T> ArrayList<T> jsonToList(String json, Class<T> classOfT) {  
  2.     Type type = new TypeToken<ArrayList<T>>() {}.getType();  
  3.     return new Gson().fromJson(json, type);  
  4. }  
這個(gè)測(cè)試能通過(guò)嗎?
  1. @Test  
  2. public void test4() {  
  3.     ArrayList<MyObj> list = jsonToList("[{x:1}]", MyObj.class);  
  4.     Assert.assertEquals(1, list.size());  
  5.     Assert.assertEquals(MyObj.class, list.get(0).getClass());  
  6. }  

答案3

答案是,方法不可行(雖然能編譯通過(guò)),測(cè)試通不過(guò)!還是因?yàn)镴ava泛型的擦除法,詳細(xì)的回答可以看stackoverflow上的這個(gè)問(wèn)題。那還有辦法實(shí)現(xiàn)jsonToList()這個(gè)通用方法呢?有的,只是稍微復(fù)雜一點(diǎn):

  1. public static <T> ArrayList<T> jsonToList(String json, Class<T> classOfT) {  
  2.     Type type = new TypeToken<ArrayList<JsonObject>>(){}.getType();  
  3.     ArrayList<JsonObject> jsonObjs = new Gson().fromJson(json, type);  
  4.       
  5.     ArrayList<T> listOfT = new ArrayList<>();  
  6.     for (JsonObject jsonObj : jsonObjs) {  
  7.         listOfT.add(new Gson().fromJson(jsonObj, classOfT));  
  8.     }  
  9.       
  10.     return listOfT;  
  11. }  
分兩步,先反序列化出ArrayList<JsonObject>,然后在一個(gè)個(gè)的把JsonObject轉(zhuǎn)成classOfT類(lèi)型的對(duì)象。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類(lèi)似文章 更多