網站首頁 編程語言 正文
Gson是谷歌官方推出的支持 JSON -- Java Object
相互轉換的 Java序列化/反序列化
庫,之前由于沒有用過,所以學習一下。
1. 導入Android Studio工程
dependencies { implementation 'com.google.code.gson:gson:2.8.4' }
2. 簡單的 Java Object 序列化/反序列化
序列化
假如有一個User
類,擁有 name
, email
, age
, isDeveloper
四個屬性,如下:
User userObject = new User( "Norman", "norman@futurestud.io", 26, true );
使用Gson將它序列化:
Gson gson = new Gson(); String userJson = gson.toJson(userObject);
得到的結果如下:
{ "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一下,查看結果
反序列化成功!
3. 嵌套 Java Object 的序列化/反序列化
也就是說,一個類里面還包含有其它類。比如User
類里面還有個用戶地址UserAddress
類,JSON結構如下:
{ "age": 26, "email": "578570174@qq.com", "isDeveloper": true, "name": "chenrenxiang", "userAddress": { "city": "Magdeburg", "country": "Germany", "houseNumber": "42A", "street": "Main Street" } }
那么這種Java Object
該如何序列化/反序列化呢?和上面一樣。也就是說和 2
里面介紹的方法一樣
4. Array 和 List 的序列化/反序列化
序列化
序列化和前面介紹的方法是一樣的
反序列化
那就有些不同了,不然也不用分開寫。
1 Array的反序列化
先假設有一個name
數組,定義JSON格式如下:
String namesJson = "['xiaoqiang','chenrenxiang','hahaha']";
然后使用Gson去反序列化它:
Gson gson = new Gson(); String[] nameArray = gson.fromJson(namesJson, String[].class);
得到的nameArray
如下:
其實這和 2
里面介紹的反序列化方法仍然是一樣的??梢钥吹?,Gson的反序列化都是調用 Gson.fromJson(...)
方法,傳入JSON字符串,以及這段JSON字符串對應的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);
對于List
,反序列化時必須提供它的Type,通過Gson
提供的TypeToken<T>.getType()
方法可以定義當前List的Type
。反序列化后結果如下:
那么,如果一個Java Object
里包含List
類型的變量,該如何反序列化這個Object
呢?答案是,和 2
一樣就行了,無需為其內部的List
提供Type
。
5. Map 和 Set 的序列化/反序列化
Map我平時用的較多,Set用的就很少了,它們的序列化/反序列化方法和List都是一樣的,反序列化的時候需要提供Type
6. 變量值為null時的序列化/反序列化
仍然以User類為例,如果一個User對象,里面的某個值為null,那么其序列化出來后的結果會是什么樣的呢?
先看序列化,我們先初始化一個User對象,并把其中的email變量賦值為null,再用Gson來序列化它,如下:
User user = new User(true, "chenrenxiang", 27, null); Gson gson = new Gson(); String userJson = gson.toJson(user);
debug一下,得到結果如下:
可見,當某個變量值為null時,Gson在序列化的時候直接把這個變量忽略了。
再來看下反序列化, 先定義一段JSON字符串,只給它一個變量值name,用User類來反序列化它,看得到的結果會是什么。
String userJson = "{'name':'xiaoqiang'}"; Gson gson = new Gson(); User user = gson.fromJson(userJson, User.class);
對于JSON字符串里沒有的變量,Gson在反序列化時會給它一個默認值,int類型默認為0,bool類型默認為false,String類型默認為null。
有人不禁要問了,如果JSON字符串里某個變量的值為null,反序列化后的結果會是什么呢?我測試過了,和沒有的結果是一樣的。
7. 控制序列化/反序列化 的變量名稱
仍然以User對象為例,目前User對象里有四個變量name
, age
, email
, isDeveloper
。假如,某一天,JSON字符串的變量名name
變成了fullName
,無需緊張,我們不用把User類里的變量name
改為fullName
,然后把它的get
和set
方法都改了,然后把用到get/set
方法的地方全改過來。只需要用Gson提供的注解方法@SerializedName
就行了,如下:
public class User { private boolean isDeveloper; @SerializedName("fullName") private String name; private int age; private String email; ... }
這樣雖然JSON字符串里的變量名為fullName
,但是反序列化后fullName
的值會映射給name
。同樣,把一個User對象序列化,變量name
會自動轉換為fullName
。
然而現實遠比想象中復雜,這個JSON有時候傳的是fullName
,有時候傳的是name
,這時該怎么辦呢? 不用擔心,@SerializedName
接受兩個參數,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的一個備選變量名,它不會影響序列化,User對象序列化后,會使用value
定義的名稱為變量名。
又想到有一個問題,在定義了value和alternate的情況下,假如JSON同時傳來了name和fullName,User的name變量會接受哪個值呢? 經過測試,它會都接受。這樣也是很合理的,因為Gson會對JSON中的變量一個一個地去解析,既然它可以接受name,也可以接受fullName,那么當同時傳來這兩個變量時,它就會分別把它們解析出來,并把值賦給User對象中的name變量。那么,name變量的值就會是后解析的那個JSON變量的值,因為它會把前一個值覆蓋掉。
8. 序列化/反序列化過程中忽略某些變量
也許會出現這樣的需求,在將某個對象序列化時,對象中的某些變量是不需要的。有可能在反序列化某個JSON字符串時,某些變量的值也是不需要的。這時就可以使用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; // 只參與序列化 }
使用這個方法,可以非常靈活地控制對象的某個/某些
變量參不參與序列化/反序列化
。
然而! 要使用這個注解來控制序列化/反序列化,就不能使用默認的Gson對象,新建Gson對象的方法如下:
GsonBuilder builder = new GsonBuilder(); builder.excludeFieldsWithoutExposeAnnotation(); Gson gson = builder.create();
注意:使用以上方式構建的Gson,在序列化/反序列化對象時,會排除所有沒有添加
@Expose
注解的字段。
另一個選擇,transient
關鍵字 ,使用這個關鍵字,可以直接讓變量不參與序列化/反序列化,如下:
public class User { String name; String email; int age; boolean transient isDeveloper; //不參與序列化/反序列化 }
當然,使用默認的Gson對象就可以。
原文鏈接:https://blog.csdn.net/chenrenxiang/article/details/80291224
相關推薦
- 2022-09-25 FFmpeg源碼分析:avformat_open_input()打開媒體流
- 2022-04-24 python文件與路徑管理方法_python
- 2023-01-11 解決?Redis?數據傾斜、熱點等問題_Redis
- 2022-10-25 C++構建函數使用介紹_C 語言
- 2022-03-19 C++?OpenCV技術實戰之身份證離線識別_C 語言
- 2022-10-16 部署k8s集群的超詳細實踐步驟_云和虛擬化
- 2022-04-02 vscode?采用C++17版本進行編譯的實現_C 語言
- 2022-10-10 Python?pygame?動畫游戲循環游戲時鐘實現原理_python
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支