Android?Gson基本用法學(xué)習(xí)
Gson是谷歌官方推出的支持 JSON -- Java Object
相互轉(zhuǎn)換的 Java序列化/反序列化
庫(kù),之前由于沒(méi)有用過(guò),所以學(xué)習(xí)一下。
1. 導(dǎo)入Android Studio工程
dependencies { implementation 'com.google.code.gson:gson:2.8.4' }
2. 簡(jiǎn)單的 Java Object 序列化/反序列化
序列化
假如有一個(gè)User
類,擁有 name
, email
, age
, isDeveloper
四個(gè)屬性,如下:
User userObject = new User( "Norman", "norman@futurestud.io", 26, true );
使用Gson將它序列化:
Gson gson = new Gson(); String userJson = gson.toJson(userObject);
得到的結(jié)果如下:
{ "isDeveloper":true, "name":"Norman", "age":26, "email":"norman@futurestud.io" }
反序列化
先定義一段JSON字符串
String userJson = "{'isDeveloper':false,'name':'xiaoqiang','age':26,'email':'578570174@qq.com'}";
Gson反序列化
User user = gson.fromJson(userJson, User.class);
debug一下,查看結(jié)果
反序列化成功!
3. 嵌套 Java Object 的序列化/反序列化
也就是說(shuō),一個(gè)類里面還包含有其它類。比如User
類里面還有個(gè)用戶地址UserAddress
類,JSON結(jié)構(gòu)如下:
{ "age": 26, "email": "578570174@qq.com", "isDeveloper": true, "name": "chenrenxiang", "userAddress": { "city": "Magdeburg", "country": "Germany", "houseNumber": "42A", "street": "Main Street" } }
那么這種Java Object
該如何序列化/反序列化呢?和上面一樣。也就是說(shuō)和 2
里面介紹的方法一樣
4. Array 和 List 的序列化/反序列化
序列化
序列化和前面介紹的方法是一樣的
反序列化
那就有些不同了,不然也不用分開(kāi)寫。
1 Array的反序列化
先假設(shè)有一個(gè)name
數(shù)組,定義JSON格式如下:
String namesJson = "['xiaoqiang','chenrenxiang','hahaha']";
然后使用Gson去反序列化它:
Gson gson = new Gson(); String[] nameArray = gson.fromJson(namesJson, String[].class);
得到的nameArray
如下:
其實(shí)這和 2
里面介紹的反序列化方法仍然是一樣的??梢钥吹?,Gson的反序列化都是調(diào)用 Gson.fromJson(...)
方法,傳入JSON字符串,以及這段JSON字符串對(duì)應(yīng)的Object類型。
2 List的反序列化
String userJson = "[{'isDeveloper':false,'name':'xiaoqiang','age':26,'email':'578570174@qq.com'},{'isDeveloper':true,'name':'xiaoqiang123','age':27,'email':'578570174@gmail.com'}]"; Gson gson = new Gson(); Type userListType = new TypeToken<ArrayList<User>>(){}.getType(); List<User> userList = gson.fromJson(userJson, userListType);
對(duì)于List
,反序列化時(shí)必須提供它的Type,通過(guò)Gson
提供的TypeToken<T>.getType()
方法可以定義當(dāng)前List的Type
。反序列化后結(jié)果如下:
那么,如果一個(gè)Java Object
里包含List
類型的變量,該如何反序列化這個(gè)Object
呢?答案是,和 2
一樣就行了,無(wú)需為其內(nèi)部的List
提供Type
。
5. Map 和 Set 的序列化/反序列化
Map我平時(shí)用的較多,Set用的就很少了,它們的序列化/反序列化方法和List都是一樣的,反序列化的時(shí)候需要提供Type
6. 變量值為null時(shí)的序列化/反序列化
仍然以User類為例,如果一個(gè)User對(duì)象,里面的某個(gè)值為null,那么其序列化出來(lái)后的結(jié)果會(huì)是什么樣的呢?
先看序列化,我們先初始化一個(gè)User對(duì)象,并把其中的email變量賦值為null,再用Gson來(lái)序列化它,如下:
User user = new User(true, "chenrenxiang", 27, null); Gson gson = new Gson(); String userJson = gson.toJson(user);
debug一下,得到結(jié)果如下:
可見(jiàn),當(dāng)某個(gè)變量值為null時(shí),Gson在序列化的時(shí)候直接把這個(gè)變量忽略了。
再來(lái)看下反序列化, 先定義一段JSON字符串,只給它一個(gè)變量值name,用User類來(lái)反序列化它,看得到的結(jié)果會(huì)是什么。
String userJson = "{'name':'xiaoqiang'}"; Gson gson = new Gson(); User user = gson.fromJson(userJson, User.class);
對(duì)于JSON字符串里沒(méi)有的變量,Gson在反序列化時(shí)會(huì)給它一個(gè)默認(rèn)值,int類型默認(rèn)為0,bool類型默認(rèn)為false,String類型默認(rèn)為null。
有人不禁要問(wèn)了,如果JSON字符串里某個(gè)變量的值為null,反序列化后的結(jié)果會(huì)是什么呢?我測(cè)試過(guò)了,和沒(méi)有的結(jié)果是一樣的。
7. 控制序列化/反序列化 的變量名稱
仍然以User對(duì)象為例,目前User對(duì)象里有四個(gè)變量name
, age
, email
, isDeveloper
。假如,某一天,JSON字符串的變量名name
變成了fullName
,無(wú)需緊張,我們不用把User類里的變量name
改為fullName
,然后把它的get
和set
方法都改了,然后把用到get/set
方法的地方全改過(guò)來(lái)。只需要用Gson提供的注解方法@SerializedName
就行了,如下:
public class User { private boolean isDeveloper; @SerializedName("fullName") private String name; private int age; private String email; ... }
這樣雖然JSON字符串里的變量名為fullName
,但是反序列化后fullName
的值會(huì)映射給name
。同樣,把一個(gè)User對(duì)象序列化,變量name
會(huì)自動(dòng)轉(zhuǎn)換為fullName
。
然而現(xiàn)實(shí)遠(yuǎn)比想象中復(fù)雜,這個(gè)JSON有時(shí)候傳的是fullName
,有時(shí)候傳的是name
,這時(shí)該怎么辦呢? 不用擔(dān)心,@SerializedName
接受兩個(gè)參數(shù),value
和 alternate
,顧名思義,alternate
是備選變量名,比如下面這段代碼:
public class User { private boolean isDeveloper; @SerializedName(value = "name", alternate = "fullName") private String name; private int age; private String email; ... }
如果JSON傳的是name
,那么就用name
的值,如果傳的是fullName
,那么就用fullName
的值。需要注意的是,alternate
只是反序列化JSON的一個(gè)備選變量名,它不會(huì)影響序列化,User對(duì)象序列化后,會(huì)使用value
定義的名稱為變量名。
又想到有一個(gè)問(wèn)題,在定義了value和alternate的情況下,假如JSON同時(shí)傳來(lái)了name和fullName,User的name變量會(huì)接受哪個(gè)值呢? 經(jīng)過(guò)測(cè)試,它會(huì)都接受。這樣也是很合理的,因?yàn)镚son會(huì)對(duì)JSON中的變量一個(gè)一個(gè)地去解析,既然它可以接受name,也可以接受fullName,那么當(dāng)同時(shí)傳來(lái)這兩個(gè)變量時(shí),它就會(huì)分別把它們解析出來(lái),并把值賦給User對(duì)象中的name變量。那么,name變量的值就會(huì)是后解析的那個(gè)JSON變量的值,因?yàn)樗鼤?huì)把前一個(gè)值覆蓋掉。
8. 序列化/反序列化過(guò)程中忽略某些變量
也許會(huì)出現(xiàn)這樣的需求,在將某個(gè)對(duì)象序列化時(shí),對(duì)象中的某些變量是不需要的。有可能在反序列化某個(gè)JSON字符串時(shí),某些變量的值也是不需要的。這時(shí)就可以使用Gson提供的@Expose
注解方法。使用方法如下:
public class User { @Expose() String name; // 參與序列化/反序列化 @Expose(serialize = false, deserialize = false) String email; // 不參與序列化,也不參與反序列化 @Expose(serialize = false) int age; // 只參與反序列化 @Expose(deserialize = false) boolean isDeveloper; // 只參與序列化 }
使用這個(gè)方法,可以非常靈活地控制對(duì)象的某個(gè)/某些
變量參不參與序列化/反序列化
。
然而! 要使用這個(gè)注解來(lái)控制序列化/反序列化,就不能使用默認(rèn)的Gson對(duì)象,新建Gson對(duì)象的方法如下:
GsonBuilder builder = new GsonBuilder(); builder.excludeFieldsWithoutExposeAnnotation(); Gson gson = builder.create();
注意:使用以上方式構(gòu)建的Gson,在序列化/反序列化對(duì)象時(shí),會(huì)排除所有沒(méi)有添加
@Expose
注解的字段。
另一個(gè)選擇,transient
關(guān)鍵字 ,使用這個(gè)關(guān)鍵字,可以直接讓變量不參與序列化/反序列化,如下:
public class User { String name; String email; int age; boolean transient isDeveloper; //不參與序列化/反序列化 }
當(dāng)然,使用默認(rèn)的Gson對(duì)象就可以。
以上所述是小編給大家介紹的Android?Gson基本用法,希望對(duì)大家有所幫助。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Android組件Glide實(shí)現(xiàn)圖片平滑滾動(dòng)效果
這篇文章主要介紹了Android組件Glide實(shí)現(xiàn)圖片平滑滾動(dòng)效果的相關(guān)資料,具有一定的參考價(jià)值,需要的朋友可以參考下2016-07-07Android ListView 實(shí)現(xiàn)上拉加載的示例代碼
這篇文章主要介紹了Android ListView 實(shí)現(xiàn)上拉加載的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-07-075個(gè)Android開(kāi)發(fā)中比較常見(jiàn)的內(nèi)存泄漏問(wèn)題及解決辦法
本文主要介紹了5個(gè)Android開(kāi)發(fā)中比較常見(jiàn)的內(nèi)存泄漏問(wèn)題及解決辦法,具有很好的參考價(jià)值,下面跟著小編一起來(lái)看下吧2017-02-02Android開(kāi)發(fā)文件存儲(chǔ)實(shí)例
這篇文章主要為大家詳細(xì)介紹了Android開(kāi)發(fā)文件存儲(chǔ)實(shí)例,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11Android實(shí)戰(zhàn)項(xiàng)目之實(shí)現(xiàn)一個(gè)簡(jiǎn)單計(jì)算器
隨著移動(dòng)互聯(lián)網(wǎng)的普及,手機(jī)應(yīng)用程序已經(jīng)成為人們生活中不可或缺的一部分,計(jì)算器是一類被廣泛使用的應(yīng)用程序之一,這篇文章主要給大家介紹了關(guān)于Android實(shí)戰(zhàn)項(xiàng)目之實(shí)現(xiàn)一個(gè)簡(jiǎn)單計(jì)算器的相關(guān)資料,需要的朋友可以參考下2023-10-10Android adb安裝apk時(shí)提示Invalid APK file的問(wèn)題
這篇文章主要介紹了Android adb安裝apk時(shí)提示Invalid APK file的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08Android開(kāi)發(fā)之OkHttpUtils的具體使用方法
這篇文章主要介紹了Android開(kāi)發(fā)之OkHttpUtils的具體使用方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-08-08Android從網(wǎng)絡(luò)中獲得一張圖片并顯示在屏幕上的實(shí)例詳解
這篇文章主要介紹了Android從網(wǎng)絡(luò)中獲得一張圖片并顯示在屏幕上的實(shí)例詳解的相關(guān)資料,希望通過(guò)本文能幫助大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-08-08Android Studio快捷鍵生成TAG、Log.x日志輸出介紹
這篇文章主要介紹了Android Studio快捷鍵生成TAG、Log.x日志輸出介紹,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-04-04