一葵诈、前言:
下一篇:Gson 的封裝使用(二): http://www.reibang.com/p/9f37bcb2274d
GSON是Google提供的用來(lái)在Java對(duì)象和JSON數(shù)據(jù)之間進(jìn)行映射的Java類庫(kù)”优洌可以將一個(gè)Json字符轉(zhuǎn)成一個(gè)Java對(duì)象,或者將一個(gè)Java轉(zhuǎn)化為Json字符串糊肠。
JSON 是一種文本形式的數(shù)據(jù)交換格式擂啥,它比XML更輕量扳还、比二進(jìn)制容易閱讀和編寫,調(diào)式也更加方便;解析和生成的方式很多橱夭。
Java中最常用的類庫(kù)有:JSON-Java氨距、Gson、Jackson棘劣、FastJson等
特點(diǎn):
- 快速俏让、高效
- 代碼量少、簡(jiǎn)潔
- 面向?qū)ο?/li>
- 數(shù)據(jù)傳遞和解析方便
二茬暇、使用
1.Gson 的依賴
implementation 'com.google.code.gson:gson:2.8.4'
2.Gson的創(chuàng)建方式:
方式一:
Gson gson = new Gson();
方式二:通過(guò)GsonBuilder()首昔,可以配置多種配置
Gson gson = new GsonBuilder()
.setLenient()// json寬松
.enableComplexMapKeySerialization()//支持Map的key為復(fù)雜對(duì)象的形式
.serializeNulls() //智能null
.setPrettyPrinting()// 調(diào)教格式
.disableHtmlEscaping() //默認(rèn)是GSON把HTML 轉(zhuǎn)義的
.create();
3. Gson的基本用法
Gson提供了fromJson() 和toJson() 兩個(gè)直接用于解析和生成的方法,前者實(shí)現(xiàn)反序列化糙俗,后者實(shí)現(xiàn)了序列化勒奇;同時(shí)每個(gè)方法都提供了重載方法
(1)基本數(shù)據(jù)類型的解析
Gson gson = new Gson();
int i = gson.fromJson("100", int.class); //100
double d = gson.fromJson("\"99.99\"", double.class); //99.99
boolean b = gson.fromJson("true", boolean.class); // true
String str = gson.fromJson("String", String.class); // String
(2)基本數(shù)據(jù)類型的生成
Gson gson = new Gson();
String jsonNumber = gson.toJson(100); // 100
String jsonBoolean = gson.toJson(false); // false
String jsonString = gson.toJson("String"); //"String"
4. 簡(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"
}
5. 簡(jiǎn)單的 Java Object 反序列化
先定義一段JSON字符串
String userJson = "{'isDeveloper':false,'name':'xiaoqiang','age':26,'email':'578570174@qq.com'}";
Gson反序列化
User user = gson.fromJson(userJson, User.class);
debug一下赊颠,查看結(jié)果
6. 嵌套 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該如何序列化/反序列化呢?和上面一樣沧奴。
7. Array 和 List 的序列化/反序列化
序列化
序列化和前面介紹的方法是一樣的
反序列化
那就有些不同了痘括,不然也不用分開寫。
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住诸。
8. Map 和 Set 的序列化/反序列化
Map我平時(shí)用的較多驾胆,Set用的就很少了涣澡,它們的序列化/反序列化方法和List都是一樣的,反序列化的時(shí)候需要提供Type
9.變量值為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é)果如下:
可見饵隙,當(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字符串里沒有的變量涮因,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ò)了,和沒有的結(jié)果是一樣的肩榕。
9. 控制序列化/反序列化 的變量名稱
仍然以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è)值覆蓋掉。
10. 序列化/反序列化過(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è)選擇,transient關(guān)鍵字 ,使用這個(gè)關(guān)鍵字纺讲,可以直接讓變量不參與序列化/反序列化,如下:
public class User {
String name;
String email;
int age;
boolean transient isDeveloper; //不參與序列化/反序列化
}
當(dāng)然囤屹,使用默認(rèn)的Gson對(duì)象就可以刻诊。
官網(wǎng)地址:https://futurestud.io/tutorials/gson-builder-basics-naming-policies