Gson使用規(guī)則

基本規(guī)范

  • 推薦使用 private 類型,支持使用 final 聲明
  • 支持 null 值蔑穴,序列化輸出時自動跳過儡陨,反序列化時直接返回null
  • 支持多維數組煞躬、Collection類型
  • 支持 URL、URI 的反序列化自動類型轉換(也可支持JodaTime轉換聋迎,參考 JodaTime Type Converter
  • 不需要定義 getter / setter 方法(通過反射設置參數值)
  • 不需要帶參構造函數脂矫,并且無參構造函數不必為 public
  • 不必要使用注解標記序列化對象,除非需要指定別名映射
  • 當前類及其所有父類的所有字段均視為默認序列化對象
  • 序列化霉晕、反序列化(如 Collection 等)泛型類型時庭再,需要通過 TypeToken 指定目標泛型的確切類型值
  • 反序列化 混合類型數組 時,可參考官方指引:Serializing and Deserializing Collection with Objects of Arbitrary Types

不屬于序列化輸出范圍

  • transient 類型字段
  • 非 static 嵌套類牺堰、內部類型
  • 經非序列化方式指定的字段

指定Json字段命名映射

Gson 默認使用類字段名作為序列化拄轻、反序列化的 Json 數據字段名。
可通過 @SerializedName(name) 注解指定該字段對應的 Json 字段名伟葫,也可以通過添加字段命名內置策略方式改變字段名輸出形式恨搓。
通過實現 FieldNamingStrategy 接口,可自定義命名映射策略筏养,通過 gsonBuilder.setFieldNamingStrategy(FieldNamingStrategy) 方式進行設定斧抱。

// 添加 @SerializedName 注解指定命名
// 可分別通過 value 和 alternate數組 指定序列化、反序列化時有效的字段命名
private class SomeObject {
  @SerializedName("custom_naming") private final String someField;
  private final String someOtherField;
}

// 添加名字映射策略撼玄,這里使用首字母大寫駝峰策略
Gson gson = new GsonBuilder()
    .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
    .create();

通過 TypeToken 指定泛型類型值

Foo<Bar> foo = new Foo<Bar>();

// 指定泛型的確切類型值
Type fooType = new TypeToken<Foo<Bar>>(){}.getType();

// 泛型序列化夺姑、反序列化,傳入泛型類型值(序列化過程可不傳入掌猛,但不保證序列化結果正確性)
gson.toJson(foo, fooType);
gson.fromJson(json, fooType);

Collection類型在序列化時受Gson內部支持盏浙,不需要指定泛型類型眉睹。

通過 TypeAdapter 徹底自定義序列化、反序列化行為

通過自定義實現 TypeAdapterJsonSerializer / JsonDeserializer 接口废膘,指定Json的序列化竹海、反序列化完整邏輯。

其中 TypeAdapter 為低層抽象類丐黄,自定義實現從流開始完全接管斋配、控制序列化行為,序列化對象為 JsonWriter / JsonReader灌闺,運行效率而言相對較高艰争。

JsonSerializer / JsonDeserializer 可按需分別指定特定類型值的序列化、反序列化的過程桂对,序列化對象為 JsonElement甩卓。

當目標對象類型不提供無參構造函數時,需要注冊一個 InstanceCreator 實現類蕉斜,用于以無參方式實例化一個目標對象逾柿。

  • (可選)實現 InstanceCreator 接口,提供以無參方式構造一個默認只能帶參構造的目標容器對象
  • (可選)實現 JsonSerializer 接口宅此,提供目標對象序列化至JsonElement類型的方法
  • (可選)實現 JsonDeserializer 接口机错,提供JsonElement類型反序列化至目標類型的方法
  • (可選)派生 TypeAdapter 子類,提供基于流的序列化父腕、反序列化完整邏輯
GsonBuilder builder = new GsonBuilder();

// 需要時注冊一個自定義 InstanceCreator 對象
builder.registerTypeAdapter(MyType.class, new MyInstanceCreator());

// 通過 registerTypeAdapter() 方法指定一個針對特定類型對象的委托序列化弱匪、反序列化器
// 第一個class類型參數必須為具體包裝類型,可指定為一個泛型
// 使用 registerTypeHierarchyAdapter 則可使用抽象父類作為類型值璧亮,但不支持泛型
builder.registerTypeAdapter(String.class, new MySerializer());
builder.registerTypeAdapter(Integer.class, new MyDeserializer());

// 通過派生 TypeAdapter 指定一個針對特定類型對象的委托序列化痢法、反序列化器
// 如果派生的 TypeAdapter 不對null參數值進行特殊處理
// 可簡單使用 new MyTypeAdapter().nullSafe() 代替
builder.registerTypeAdapter(MyType2.class, new MyTypeAdapter());

Gson gson = builder.create();

注冊使用 JsonSerializerJsonDeserializer杜顺、TypeAdapter财搁、TypeAdapterFactory 等自定義序列化處理器時,對于同一目標類型的(反)序列化以最后一個注冊為準躬络。
Gson的處理優(yōu)先順序為 registerTypeAdapter() > 注解 > 內置TypeAdapter 尖奔,在注冊指定序列化處理器時,Gson注解等內置自動序列化系統(tǒng)將失效(控制權由自定義處理器掌控)穷当。

參考:

關于 null 的支持

默認狀態(tài)下提茁,null 值的對象在序列化 Json 過程中會直接忽略,不輸出到 Json 結果馁菜,但可通過以下方式簡單的啟用 null 輸出:gsonBuilder.serializeNulls().create()

反序列化時茴扁,傳入空的Json或null或"null",將直接返回null

輸出 Json 效果如:

gson.toJson(stuff) -> {"name":null,"number":5}
gson.toJson(null) -> null

gson.fromJson("", Type.class) -> null

序列化版本支持

可指定某些字段僅在特定版本下實施序列化汪疮,比序列化所用 Gson 對象指定版本更高的字段將被忽略峭火。

public class VersionedClass {

  // 通過 @Since 和 @Until 注解指定該字段的有效起始版本(包含)毁习、有效到期版本(不包含)
  @Since(1.1) private final String newerField;

  @Since(1.0) private final String newField;

  @Until(2.0) private final String oldField;

  private final String field;
}

// 指定 1.0 版本時,序列化輸出 Json 不包括 1.1 版本及以上的字段 newerField
// 但包含 2.0 版本以下時可用的字段 oldField
Gson gson = new GsonBuilder().setVersion(1.0).create();
...

// 不指定版本時卖丸,版本機制無效纺且,所有字段都將輸出到結果 Json
gson = new Gson();
...

使用內置的方案篩選非序列化字段

默認狀態(tài)下Gson自動排除經 transient 聲明的字段。
除此之外稍浆,可在 GsonBuilder 中通過以下兩種方式添加額外的排除方案:

// 通過 excludeFieldsWithModifiers 指定需要排除的修飾符
Gson gson = new GsonBuilder()
    .excludeFieldsWithModifiers(Modifier.STATIC, Modifier.TRANSIENT, Modifier.VOLATILE)
    .create();


// 通過 @Expose 注解標記可以序列化的合法字段
// 其中可選分別指定 serialize 和 deserialize 的有效性
// @Expose = @Expose(serialize = true, deserialize = true)
@Expose private final String fieldForOutput;
final String fieldForCacheLocally;

gson = new GsonBuilder()
    .excludeFieldsWithoutExposeAnnotation()
    .create();

使用自定義方案識別非序列化字段

派生 ExclusionStrategy 子類载碌,覆蓋指定方法,以代碼邏輯方式判斷需要排除的字段類型衅枫、注解標記嫁艇、字段值等特征。

Gson gson = new GsonBuilder()
    .setExclusionStrategies(new MyExclusionStrategy(String.class))
    .addSerializationExclusionStrategy(ExclusionStrategy)
    .addDeserializationExclusionStrategy(ExclusionStrategy)
    .create();
參考:

其他可選格式化設置

通過 GsonBuilder 可鏈式設置多種格式化方案:

  • serializeNulls():允許序列化輸出 null
  • setDateFormat("yyyy-MM-dd"):設置序列化弦撩、反序列化時使用的日期格式
  • disableInnerClassSerialization():禁止序列化內部類
  • generateNonExecutableJson():生成JS中不可執(zhí)行的 Json(在前綴插入一些特殊字符)
  • disableHtmlEscaping():禁用Html自動轉義
  • setPrettyPrinting():以可讀格式輸出裳仆,默認序列化Json不包含空格,使用可讀格式輸出時將激活內置的JsonPrintFormatter孤钦,生成添加額外空格縮進排版的Json字符串(格式不可自定義)
  • serializeSpecialFloatingPointValues():允許序列化特殊浮點標記值,如 NAN纯丸、Infinity偏形、-Infinity
  • enableComplexMapKeySerialization():允許序列化復合型key(如一個自定義對象等)

其他文獻參考

你真的會用Gson嗎?Gson使用指南

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市觉鼻,隨后出現的幾起案子俊扭,更是在濱河造成了極大的恐慌,老刑警劉巖坠陈,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件萨惑,死亡現場離奇詭異,居然都是意外死亡仇矾,警方通過查閱死者的電腦和手機庸蔼,發(fā)現死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來贮匕,“玉大人姐仅,你說我怎么就攤上這事】萄危” “怎么了掏膏?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長敦锌。 經常有香客問我馒疹,道長,這世上最難降的妖魔是什么乙墙? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任颖变,我火速辦了婚禮生均,結果婚禮上,老公的妹妹穿的比我還像新娘悼做。我一直安慰自己疯特,他們只是感情好,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布肛走。 她就那樣靜靜地躺著漓雅,像睡著了一般。 火紅的嫁衣襯著肌膚如雪朽色。 梳的紋絲不亂的頭發(fā)上邻吞,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機與錄音葫男,去河邊找鬼抱冷。 笑死,一個胖子當著我的面吹牛梢褐,可吹牛的內容都是我干的旺遮。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼盈咳,長吁一口氣:“原來是場噩夢啊……” “哼耿眉!你這毒婦竟也來了?” 一聲冷哼從身側響起鱼响,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤鸣剪,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后丈积,有當地人在樹林里發(fā)現了一具尸體筐骇,經...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年江滨,在試婚紗的時候發(fā)現自己被綠了铛纬。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡唬滑,死狀恐怖饺鹃,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情间雀,我是刑警寧澤悔详,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站惹挟,受9級特大地震影響茄螃,放射性物質發(fā)生泄漏。R本人自食惡果不足惜连锯,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一归苍、第九天 我趴在偏房一處隱蔽的房頂上張望用狱。 院中可真熱鬧,春花似錦拼弃、人聲如沸夏伊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽溺忧。三九已至,卻和暖如春盯孙,著一層夾襖步出監(jiān)牢的瞬間鲁森,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工振惰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留歌溉,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓骑晶,卻偏偏與公主長得像痛垛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子桶蛔,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內容

  • 1.概述2.Gson的目標3.Gson的性能和擴展性4.Gson的使用者5.如何使用Gson 通過Maven來使用...
    人失格閱讀 14,222評論 2 18
  • 為了更好的學習Gson匙头,特將Gson User Guide翻譯如下。由于本人英文水平有限羽圃,如有錯誤,還請指正抖剿,謝謝...
    WeberLisper閱讀 6,763評論 0 6
  • 產品設計朽寞,要迎合市場。除了自身要具備極工業(yè)制造原理斩郎,還要有極強的藝術品鑒賞能力脑融。 剛性的工業(yè)遇到柔性的藝術設...
    牛田春水閱讀 203評論 0 0
  • 該內容參考地址 過程概述 瀏覽器查找域名對應的 IP 地址; 瀏覽器根據 IP 地址與服務器建立 socket 連...
    Ann_l閱讀 414評論 1 1
  • 寂寞是江南小巷里的一堵墻 墻外春光明媚 一支紅杏 伸出墻外 格外妖嬈 寂寞是宋代街市中的一扇窗 窗外有人走來 一個...
    思饗反動閱讀 87評論 0 0