最全Gson使用
Gson是Google開源的一個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)建的方式更靈活,因為它支持對Gson的配置。
將對象轉(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中的泛型存在類型擦除的問題,所以使用泛型接收JSON解析結(jié)果的時候有點特殊。
普通對象解析
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ā)中有時會對Bean對象進行復(fù)用,但可能有幾個字段的命名和當前的對象不一致,這樣在解析JSON的時候就不能正確賦值。Gson提供了字段復(fù)用功能——@SerializedName,可用一個字段接收不同的JSON字段。
// json字符串中手機號的字段為phone或telNumber時都可正確解析 @SerializedName("phone") private String telNumber; // json字符串中用戶名的字段為userName、user_name、uname或u_name時都可正確解析 @SerializedName(value = "userName", alternate = {"user_name", "uname", "u_name"}) private String userName;
Gson配置
除了以上用法,Gson還提供了豐富的配置選項,包括:空值過濾,字段命名規(guī)則,自定義解析器,自定義序列化/反序列化等。
空值問題
Gson默認情況下會過濾空值字段,但有時在提交數(shù)據(jù)給后臺時,即便字段為空,也需要傳給后臺,此時可通過GsonBuilder進行配置。
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)換的時候沒有輸出password字段。
字段命名轉(zhuǎn)換規(guī)則
因為不同的語言使用不同的命名規(guī)則,這會出現(xiàn)為了正確解析JSON字符串,而使用不符合命名規(guī)則的字段名。如PHP使用小寫字母下劃線分割的命名方式,而Java使用駱駝命名的方式,這樣Android程序在接收JSON字符串的時候就需要使用小寫字母下劃線分割的命名方式,然而這并不符合Java的命名規(guī)范。為了解決這個問題,Gson提供了豐富的字段命名規(guī)則。
// 默認的字段轉(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();
當然,如果上面幾種命名轉(zhuǎn)換規(guī)則不滿足需求,也可自定義命名轉(zhuǎn)換規(guī)則,只需要實現(xiàn)FieldNamingStrategy接口,并完善translateName方法即可。需要注意的是,命名轉(zhuǎn)換規(guī)則會同時被應(yīng)用于序列化和反發(fā)序列化,所以在將對象轉(zhuǎn)換為JSON(序列化)傳給后臺時需要注意。
字段過濾
默認情況下,Gson將對象轉(zhuǎn)換為JSON時,會將所有非null字段進行轉(zhuǎn)換,但有時為了業(yè)務(wù)需求,通常會添加一些狀態(tài)字段,如表示item選中狀態(tài)的isSelected,這些字段通常不希望被轉(zhuǎn)換。Gson提供了多種過濾方式,這里說說兩種最常用的。
通過修飾符過濾
Gson gson = new GsonBuilder() // 過濾transient或static修飾的字段, .excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.STATIC).create();
自定義過濾規(guī)則
通過實現(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ī)則同時適用于序列化/反序列化 ?? ?.setExclusionStrategies(strategy) ?? ?// 過濾規(guī)則只適用于序列化 ?? ?.addSerializationExclusionStrategy(strategy) ?? ?// 過濾規(guī)則只適用于反序列化 ?? ?.addDeserializationExclusionStrategy(strategy) ?? ?.create();
字段容錯性
字段容錯性主要表現(xiàn)在字段的類型不匹配,比如接收的字段是整型,返回的卻是字符串或者null, 這種情況情況直接使用String接收整型倒可以解決,但對于接收類型是數(shù)組,返回的確是對象的情況,卻不能直接使用類型兼容來處理。
雖然這些情況都是因為后臺數(shù)據(jù)格式的問題,但對用戶最直觀的感受是APP閃退了。所以我們需要對JSON的解析過程做一定的兼容處理,以防出現(xiàn)異常數(shù)據(jù)時導(dǎo)致APP閃退。
開發(fā)中經(jīng)常遇到的類型兼容問題匯總:
- 使用Number類型接收,返回了String或空值(Gson已處理此類問題);
- 使用數(shù)組接收,返回了對象類型;
Gson提供了多種序列化/反序列化方式,由于這里我們只做JSON解析(即反序列化)的兼容處理,所以直接實現(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容錯性 .registerTypeHierarchyAdapter(List.class, listDeserial) .create();
總結(jié)
到此這篇關(guān)于最全Gson使用的文章就介紹到這了,更多相關(guān)Gson使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用SpringBoot集成Thymeleaf和Flying?Saucer實現(xiàn)PDF導(dǎo)出
在?Spring?Boot?項目中,生成?PDF?報表或發(fā)票是常見需求,本文將介紹如何使用?Spring?Boot?集成?Thymeleaf?模板引擎和?Flying?Saucer?實現(xiàn)?PDF?導(dǎo)出,并提供詳細的代碼實現(xiàn)和常見問題解決方案,需要的朋友可以參考下2024-11-11Spring Data MongoDB中實現(xiàn)自定義級聯(lián)的方法詳解
這篇文章主要給大家介紹了關(guān)于Spring Data MongoDB中實現(xiàn)自定義級聯(lián)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-11-11java Timer 定時每天凌晨1點執(zhí)行任務(wù)
這篇文章主要介紹了java Timer 定時每天凌晨1點執(zhí)行任務(wù)的代碼,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-09-09Admin - SpringBoot + Maven 多啟動環(huán)境配置實例詳解
這篇文章主要介紹了Admin - SpringBoot + Maven 多啟動環(huán)境配置,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-03-03Java抓包工具fiddler實現(xiàn)請求轉(zhuǎn)發(fā)
Fiddler是一個http協(xié)議調(diào)試代理工具,本文主要介紹了Java抓包工具fiddler實現(xiàn)請求轉(zhuǎn)發(fā),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-04-04