最全Gson使用
Gson是Google開源的一個(gè)JSON庫,被廣泛應(yīng)用在Android開發(fā)中。
說明:以下所有的用法都基于Account類!
public class Account {
?? ?private String uid;
?? ?private String userName;
?? ?private String password;
?? ?private String telNumber;
?? ?public Account(String uid, String userName, String telNumber) {
?? ??? ?this.uid = uid;
?? ??? ?this.userName = userName;
?? ??? ?this.telNumber = telNumber;
?? ?}
?? ?@Override
?? ?public String toString() {
?? ??? ?return "Account [uid=" + uid + ", userName=" + userName + ", password=" + password + ", telNumber=" + telNumber
?? ??? ??? ??? ?+ "]";
?? ?}
}基礎(chǔ)用法
集成Gson
dependencies {
implementation 'com.google.code.gson:gson:2.8.5'
}創(chuàng)建Gson對象
Gson提供了兩種創(chuàng)建對象的方式:
直接使用Gson構(gòu)造方法創(chuàng)建;
Gson gson = new Gson();
使用GsonBuilder創(chuàng)建;
Gson gson = new GsonBuilder().create();
相比直接使用構(gòu)造方法,GsonBuilder創(chuàng)建的方式更靈活,因?yàn)樗С謱son的配置。
將對象轉(zhuǎn)換為JSON
Account account = new Account("00001", "Freeman", "13000000000");
System.out.println(gson.toJson(account));
ArrayList<Account> accountList = new ArrayList<Account>();
accountList.add(account);
System.out.println(gson.toJson(accountList));結(jié)果:
{"uid":"00001","userName":"Freeman","telNumber":"13000000000"}
[{"uid":"00001","userName":"Freeman","telNumber":"13000000000"}]
將JSON轉(zhuǎn)換為對象
由于Java中的泛型存在類型擦除的問題,所以使用泛型接收J(rèn)SON解析結(jié)果的時(shí)候有點(diǎn)特殊。
普通對象解析
String json = "{\"uid\":\"00001\",\"userName\":\"Freeman\",\"telNumber\":\"13000000000\"}";
Account receiveAccount = gson.fromJson(json, Account.class);
System.out.println(receiveAccount.toString());結(jié)果:
Account [uid=00001, userName=Freeman, password=null, telNumber=13000000000]
泛型對象解析
String listJson = "[{\"uid\":\"00001\",\"userName\":\"Freeman\",\"telNumber\":\"13000000000\"}]";
List receiveAccountList = gson.fromJson(listJson, new TypeToken<List<Account>>(){}.getType());
System.out.println("receiveAccountList size = " + receiveAccountList.size());結(jié)果:
receiveAccountList size = 1
字段復(fù)用
在開發(fā)中有時(shí)會對Bean對象進(jìn)行復(fù)用,但可能有幾個(gè)字段的命名和當(dāng)前的對象不一致,這樣在解析JSON的時(shí)候就不能正確賦值。Gson提供了字段復(fù)用功能——@SerializedName,可用一個(gè)字段接收不同的JSON字段。
// json字符串中手機(jī)號的字段為phone或telNumber時(shí)都可正確解析
@SerializedName("phone")
private String telNumber;
// json字符串中用戶名的字段為userName、user_name、uname或u_name時(shí)都可正確解析
@SerializedName(value = "userName", alternate = {"user_name", "uname", "u_name"})
private String userName;Gson配置
除了以上用法,Gson還提供了豐富的配置選項(xiàng),包括:空值過濾,字段命名規(guī)則,自定義解析器,自定義序列化/反序列化等。
空值問題
Gson默認(rèn)情況下會過濾空值字段,但有時(shí)在提交數(shù)據(jù)給后臺時(shí),即便字段為空,也需要傳給后臺,此時(shí)可通過GsonBuilder進(jìn)行配置。
gson = new GsonBuilder().serializeNulls().create();
Account account = new Account("00001", "Freeman", "13000000000");
System.out.println(gson.toJson(account));結(jié)果:
{"uid":"00001","userName":"Freeman","password":null,"phone":"13000000000"}
從結(jié)果可以看出,password字段被輸出了,而前面直接創(chuàng)建Gson轉(zhuǎn)換的時(shí)候沒有輸出password字段。
字段命名轉(zhuǎn)換規(guī)則
因?yàn)椴煌恼Z言使用不同的命名規(guī)則,這會出現(xiàn)為了正確解析JSON字符串,而使用不符合命名規(guī)則的字段名。如PHP使用小寫字母下劃線分割的命名方式,而Java使用駱駝命名的方式,這樣Android程序在接收J(rèn)SON字符串的時(shí)候就需要使用小寫字母下劃線分割的命名方式,然而這并不符合Java的命名規(guī)范。為了解決這個(gè)問題,Gson提供了豐富的字段命名規(guī)則。
// 默認(rèn)的字段轉(zhuǎn)換規(guī)則,字段名不變 FieldNamingPolicy.IDENTITY() // 將json中的字段名轉(zhuǎn)換為首字母大寫的格式 FieldNamingPolicy.UPPER_CAMEL_CASE() 如:"user_name" -> "UserName" // 將json中的字段名轉(zhuǎn)換為首字母大寫,單詞之間以空格分割的格式 FieldNamingPolicy.UPPER_CAMEL_CASE_WITH_SPACES() 如:"user_name" -> "User Name" // 將json中的字段名轉(zhuǎn)換為小寫字母,單詞之間以下劃線分割的格式 FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES() 如:"UserName" -> "user_name" // 將json中的字段名轉(zhuǎn)換為小寫字母,單詞之間以分隔線分割的格式 FieldNamingPolicy.LOWER_CASE_WITH_DASHES() 如:"UserName" -> "user-name"
所以對于服務(wù)器是PHP的情況,Android端可使用FieldNamingPolicy.UPPER_CAMEL_CASE轉(zhuǎn)換規(guī)則。
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.create();當(dāng)然,如果上面幾種命名轉(zhuǎn)換規(guī)則不滿足需求,也可自定義命名轉(zhuǎn)換規(guī)則,只需要實(shí)現(xiàn)FieldNamingStrategy接口,并完善translateName方法即可。需要注意的是,命名轉(zhuǎn)換規(guī)則會同時(shí)被應(yīng)用于序列化和反發(fā)序列化,所以在將對象轉(zhuǎn)換為JSON(序列化)傳給后臺時(shí)需要注意。
字段過濾
默認(rèn)情況下,Gson將對象轉(zhuǎn)換為JSON時(shí),會將所有非null字段進(jìn)行轉(zhuǎn)換,但有時(shí)為了業(yè)務(wù)需求,通常會添加一些狀態(tài)字段,如表示item選中狀態(tài)的isSelected,這些字段通常不希望被轉(zhuǎn)換。Gson提供了多種過濾方式,這里說說兩種最常用的。
通過修飾符過濾
Gson gson = new GsonBuilder() // 過濾transient或static修飾的字段, .excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.STATIC).create();
自定義過濾規(guī)則
通過實(shí)現(xiàn)setExclusionStrategies接口來定義過濾規(guī)則:
ExclusionStrategy strategy = new ExclusionStrategy() {
?? ?@Override
?? ?public boolean shouldSkipClass(Class<?> arg0) {
?? ??? ?// 過濾指定的類
?? ??? ?return false;
?? ?}
?? ?@Override
?? ?public boolean shouldSkipField(FieldAttributes arg0) {
?? ??? ?// 過濾指定的字段
?? ??? ?return false;
?? ?}
};
Gson gson = new GsonBuilder()
?? ?// 過濾規(guī)則同時(shí)適用于序列化/反序列化
?? ?.setExclusionStrategies(strategy)
?? ?// 過濾規(guī)則只適用于序列化
?? ?.addSerializationExclusionStrategy(strategy)
?? ?// 過濾規(guī)則只適用于反序列化
?? ?.addDeserializationExclusionStrategy(strategy)
?? ?.create();字段容錯(cuò)性
字段容錯(cuò)性主要表現(xiàn)在字段的類型不匹配,比如接收的字段是整型,返回的卻是字符串或者null, 這種情況情況直接使用String接收整型倒可以解決,但對于接收類型是數(shù)組,返回的確是對象的情況,卻不能直接使用類型兼容來處理。
雖然這些情況都是因?yàn)楹笈_數(shù)據(jù)格式的問題,但對用戶最直觀的感受是APP閃退了。所以我們需要對JSON的解析過程做一定的兼容處理,以防出現(xiàn)異常數(shù)據(jù)時(shí)導(dǎo)致APP閃退。
開發(fā)中經(jīng)常遇到的類型兼容問題匯總:
- 使用Number類型接收,返回了String或空值(Gson已處理此類問題);
- 使用數(shù)組接收,返回了對象類型;
Gson提供了多種序列化/反序列化方式,由于這里我們只做JSON解析(即反序列化)的兼容處理,所以直接實(shí)現(xiàn)JsonDeserializer接口即可。
// 為數(shù)組類型自定義反序列化適配器
JsonDeserializer<List<?>> listDeserial = new JsonDeserializer<List<?>>() {
?? ?@Override
?? ?public List<?> deserialize(JsonElement arg0, java.lang.reflect.Type arg1,
?? ??? ??? ?JsonDeserializationContext arg2) throws JsonParseException {
?? ??? ?if (arg0.isJsonArray()) {
?? ??? ??? ?JsonArray jsonArray = arg0.getAsJsonArray();
?? ??? ??? ?if (jsonArray.size() == 0) {
?? ??? ??? ??? ?return Collections.EMPTY_LIST;
?? ??? ??? ?}
?? ??? ??? ?List<?> resultList = new ArrayList<>();
?? ??? ??? ?for (JsonElement element : jsonArray) {
?? ??? ??? ??? ?resultList.add(arg2.deserialize(element, arg1));
?? ??? ??? ?}
?? ??? ??? ?return resultList;
?? ??? ?} else {
?? ??? ??? ?return Collections.EMPTY_LIST;
?? ??? ?}
?? ?}
};
Gson gson = new GsonBuilder()
? ? // 注冊自定義的反序列化適配器
?? ?.registerTypeHierarchyAdapter(List.class, listDeserial)
?? ?.create();Gson常用配置總結(jié)
gson = new GsonBuilder()
// 不過濾空值
.serializeNulls()
// 設(shè)置字段命名轉(zhuǎn)換規(guī)則
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
// 設(shè)置字段序列化/反序列化過濾規(guī)則
.excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.STATIC)
// 自定義類型解析器,提高Gson容錯(cuò)性
.registerTypeHierarchyAdapter(List.class, listDeserial)
.create();總結(jié)
到此這篇關(guān)于最全Gson使用的文章就介紹到這了,更多相關(guān)Gson使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用SpringBoot集成Thymeleaf和Flying?Saucer實(shí)現(xiàn)PDF導(dǎo)出
在?Spring?Boot?項(xiàng)目中,生成?PDF?報(bào)表或發(fā)票是常見需求,本文將介紹如何使用?Spring?Boot?集成?Thymeleaf?模板引擎和?Flying?Saucer?實(shí)現(xiàn)?PDF?導(dǎo)出,并提供詳細(xì)的代碼實(shí)現(xiàn)和常見問題解決方案,需要的朋友可以參考下2024-11-11
Spring Data MongoDB中實(shí)現(xiàn)自定義級聯(lián)的方法詳解
這篇文章主要給大家介紹了關(guān)于Spring Data MongoDB中實(shí)現(xiàn)自定義級聯(lián)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11
詳細(xì)解讀Druid數(shù)據(jù)庫連接池的使用
這篇文章主要介紹了Druid數(shù)據(jù)庫連接池的使用,數(shù)據(jù)庫連接池負(fù)責(zé)分配、管理和釋放數(shù)據(jù)庫連接,它允許應(yīng)用程序重復(fù)使用一個(gè)現(xiàn)有的數(shù)據(jù)庫連接,而不是重新建立一個(gè),需要的朋友可以參考下2023-03-03
java Timer 定時(shí)每天凌晨1點(diǎn)執(zhí)行任務(wù)
這篇文章主要介紹了java Timer 定時(shí)每天凌晨1點(diǎn)執(zhí)行任務(wù)的代碼,代碼簡單易懂,非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-09-09
Admin - SpringBoot + Maven 多啟動環(huán)境配置實(shí)例詳解
這篇文章主要介紹了Admin - SpringBoot + Maven 多啟動環(huán)境配置,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
Java抓包工具fiddler實(shí)現(xiàn)請求轉(zhuǎn)發(fā)
Fiddler是一個(gè)http協(xié)議調(diào)試代理工具,本文主要介紹了Java抓包工具fiddler實(shí)現(xiàn)請求轉(zhuǎn)發(fā),文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04

