原文鏈接:Gson Advanced — Generics
原文出自:Norman Peitek
譯者:無名無
本文將介紹使用 Gson 來解析 Java 泛型類型的數據結構,如果不瞭解泛型基本知識的可以回顧 Wikipedia article,同樣 Gson 會幫我們完成解析。
泛型序列化
之前使用 Gson 來解析 Java 對象,我們必須傳入要解析的 Java class 類型,先來看例子。
兩個 List:
Gson gson = new Gson();
List<Integer> integerList = new ArrayList<>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
List<String> stringList = new ArrayList<>();
stringList.add("1");
stringList.add("2");
stringList.add("3");
String integerJson = gson.toJson(integerList);
String stringJson = gson.toJson(stringList);
每種數據類型需要 new TypeToken 才能解析成功:
Gson gson = new Gson();
List<Integer> integerList = new ArrayList<>();
integerList.add(1);
integerList.add(2);
integerList.add(3);
List<String> stringList = new ArrayList<>();
stringList.add("1");
stringList.add("2");
stringList.add("3");
Type integerType = new TypeToken<List<Integer>>() {}.getType();
Type stringType = new TypeToken<List<String>>() {}.getType();
String integerJson = gson.toJson(integerList, integerType);
String stringJson = gson.toJson(stringList, stringType);
輸出:
integerJson = "[1,2,3]"
stringJson = "["1","2","3"]"
再來看一個泛型封裝的例子 Box,只包含了一個泛型對象:
public class Box<T> {
private T boxContent;
public Box(T t) {
this.boxContent = t;
}
}
Gson gson = new Gson();
Box<String> stringBox = new Box<>("String Type");
Box<Integer> integerBox = new Box<>(42);
// the class UserDate is from previous guides (https://futurestud.io/blog/gson-builder-formatting-of-dates-custom-date-time-mapping/)
Box<UserDate> complexBox = new Box<>(new UserDate("Norman", "[email protected]", 26, true));
Type stringType = new TypeToken<Box<String>>() {}.getType();
Type integerType = new TypeToken<Box<Integer>>() {}.getType();
Type complexType = new TypeToken<Box<UserDate>>() {}.getType();
String integerJson = gson.toJson(integerBox, integerType);
String stringJson = gson.toJson(stringBox, stringType);
String complexJson = gson.toJson(complexBox, complexType);
輸出:
integerJson:{"boxContent":42}
stringJson:{"boxContent":"String Type"}
complexJson:{"boxContent":{"_name":"Norman","email":"[email protected]","isDeveloper":true,"age":26,"registerDate":"Dec 4, 2016 10:21:24 AM"}}
反序列化泛型
假設有一段這樣的 JSON 數據,我們使用 Box 泛型來解析。
{
"boxContent": {
"_name": "Norman",
"age": 26,
"email": "[email protected]",
"isDeveloper": true,
"registerDate": "Jun 7, 2016 7:15:29 AM"
}
}
首先我們要明確 JSON 屬於 Box 中泛型的哪種類型,知道了泛型的類型,我們就能確認 TypeToken 的類型。
String complexGenericJson = "{\"boxContent\":{\"_name\":\"Norman\",\"age\":26,\"email\":\"[email protected]\",\"isDeveloper\":true,\"registerDate\":\"Jun 7, 2016 7:15:29 AM\"}}";
Type complexType = new TypeToken<Box<UserDate>>() {}.getType();
Gson gson = new Gson();
Box boxWithData = gson.fromJson(complexGenericJson, complexType);
Box<UserDate> boxWithoutData = gson.fromJson(complexGenericJson, Box.class);
System.out.println("boxWithoutData:" + boxWithoutData);
System.out.println("boxWithData:" + boxWithData);
輸出:
boxWithoutData:Box{boxContent={_name=Norman, age=26.0, [email protected], isDeveloper=true, registerDate=Jun 7, 2016 7:15:29 AM}}
boxWithData:Box{boxContent=UserDate{_name='Norman', email='[email protected]', isDeveloper=true, age=26, registerDate=Tue Jun 07 07:15:29 CST 2016}}
解析泛型的關鍵就是我們要知道最終要解析成那種泛型類型。如果你想知道更多關於 Gson 如何處理內部 Java 泛型的,可以閱讀 [official user guide](official user guide)
目標
瞭解 Gson 泛型使用,針對泛型解析有一些需要注意的情況以及實際應用。
練習代碼已上傳 Github https://github.com/whiskeyfei/Gson-Review 可自行查看。
Gson 系列文章翻譯回顧
1、Gson - Java-JSON 序列化和反序列化入門
2、Gson - 映射嵌套對象
3、Gson - Arrays 和 Lists 映射對象
4、Gson - Map 結構映射
5、Gson - Set 集合映射
6、Gson - 空值映射
7、Gson Model Annotations - 如何使用 @SerializedName 更改字段的命名
8、Gson Model Annotations - @SerializedName 匹配多個反序列化名稱
9、Gson Builder - 基礎和命名規則
10、Gson Builder - 序列化空值
11、Gson Builder - 忽略策略
12、Gson Builder - Gson Lenient 屬性
13、Gson Builder - 特殊類型 Floats & Doubles
17、Gson Builder - 如何使用 @Expose 忽略字段
19、Gson Advanced - 映射枚舉類型
20、Gson Advanced - 映射循環引用
21、Gson Advanced - 泛型
22、Gson Advanced - 簡單自定義序列化 (Part 1)
24、Gson Advanced - 自定義反序列化基礎
25、Gson Advanced - 自定義對象實例創建
26、Gson Advanced - 通過 @JsonAdapter 自定義(反)序列化過程
32、Practical Gson - 如何解析多態對象