Android:Gson解析——從簡單資料到複雜資料
Json是一種輕量級的資料交換語言,以文字為基礎,且易於讓人閱讀和編寫,同時也易於機器解析和生成,因而在客戶端與伺服器互動中得到廣泛應用。但Json自帶的解析類用起來卻差強人意,所以市面上因運而生了很多Json轉換利器,本文主要介紹其中之一Gson。Gson是google釋出的library,主要為了方便將Java物件序列化Serialization至輕量化的封包格式JSON,提供了很多方便快捷的方法。
通過gradle匯入包
登入網站MVNRepository,在搜尋框中搜索gson,即可出現各種不同的版本,選擇gradle下需要的版本,並複製到gradle檔案中即可。
Gson基本用法
Gson提供了兩個方法直接用於解析和生成方法,二者都有過載方法:
- fromJson():實現反序列化
- toJson():實現序列化
基本資料型別的生成
Gson gson = new Gson();
String jsonNumber = gson.toJson(100); // 100
String jsonBoolean = gson.toJson(false); // false
String jsonString = gson.toJson("String"); //"String"
POJO類的生成與解析
對於普通Java類:
public class User {
public String name;
public int age;
}
生成JSON
Gson gson = new Gson();
User user = new User("Sunny",24);
String jsonObject = gson.toJson(user); // {"name":"Sunny","age":24}
解析JSON
Gson gson = new Gson();
String jsonString = "{\"name\":\"sunny\",\"age\":24}";
User user = gson.fromJson(jsonString, User.class);
注:POJO(Plain Old Java Object)表示普通Java物件,不是JavaBean,EntityBean或者SessionBean。POJO不擔當任何特殊的角色,也不實現任何特殊的Java框架的介面。
Gson中的泛型
當我們解析Json陣列時,一般有兩種方式:使用陣列,使用List。而List對於增刪都比較方便,所以實際用List較多
陣列
String[] strings = gson.fromJson(jsonArray, String[].class);
但對於List將上面程式碼中的 String[].class
,不能直接改為List<String>.class
。對於Java來說 List<String>
和List<User>
這兩個位元組碼檔案只有一個,就是 List.class
,這就是Java泛型使用時要注意的泛型擦除問題。
List
為了解決上述問題,Gson提供TypeToken
來實現對泛型的支援。TypeToken 這個類幫助我們捕獲(capture)像 List 這樣的泛型資訊。Java編譯器會把捕獲到的泛型資訊編譯到這個匿名內部類裡,然後在執行時就可以被 getType() 方法用反射的 API 提取到。也就是將泛型T轉成 .class
List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());
注:TypeToken
的構造方法是protected
修飾的,所以上面才會寫成new TypeToken<List<String>>() {}.getType()
而不是new TypeToken<List<String>>().getType()
@Expose、@SerializeName註解的使用
Json解析的欄位和值得名稱和型別是一一對應的,但有時前端和後臺使用的語言不同,二者語言規範風格不同,命名時常常會出現不和諧的地方。這時 @Expose @SerializeName 兩個註解就要發揮他們的作用啦
- @Expose註解:區分實體中不想被序列化的屬性,其自身包含兩個屬性deserialize(反序列化)和serialize(序列化),預設都為true
- @SerializeName註解:定義屬性序列化後的名稱
使用 new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();建立Gson物件,沒有@Expose註釋的屬性將不會被序列化.。另外想要不序列化某個屬性,也可以使用transient。
Gson在序列化和反序列化時需要使用反射,說到反射就想到註解,一般各類庫都將註解放到annotations包下,開啟原始碼在com.google.gson包下有一個annotations類,其中有一個SerializedName的註解類,這就是我們用到的。
Gson解析複雜Json資料
首先,要知道兩個類:
1、JsonParse
從名稱我們就可以看出,這是一個解析類。沒錯,它可以把 JSON 資料分別通過getAsJsonObject
和getAsJsonArray
解析成JsonObject
和JsonArray
。這跟普通的解析 JSON 差不多。
2、JsonElement
是一個抽象類,代表 JSON 串中的某一個元素,可以是JsonObject/JsonArray/JsonPrimitive/...
中的任何一種元素。
沒有資料頭的純陣列
JSON裡面只有一個數組,而陣列中沒有名字:
[
{
"name": "zhangsan",
"age": "10",
"phone": "11111",
"email": "[email protected]"
},
{
"name": "lisi",
"age": "20",
"phone": "22222",
"email": "[email protected]"
},
...
]
開始解析,首先定義一個使用者類:
public class UserBean {
//變數名跟JSON資料的欄位名需要一致
private String name ;
private String age;
private String phone;
private String email;
...
}
方法一:Gson可以直接解析成一個List
List<UserBean> userList = gson.fromJson(jsonStr, new TypeToken<List<UserBean>>(){}.getType());
方法二:傳統老實方法
//Json的解析類物件
JsonParser parser = new JsonParser();
//將JSON的String 轉成一個JsonArray物件
JsonArray jsonArray = parser.parse(strByJson).getAsJsonArray();
Gson gson = new Gson();
ArrayList<UserBean> userBeanList = new ArrayList<>();
//加強for迴圈遍歷JsonArray
for (JsonElement user : jsonArray) {
//使用GSON,直接轉成Bean物件
UserBean userBean = gson.fromJson(user, UserBean.class);
userBeanList.add(userBean);
}
有資料頭的純陣列資料
{
"user": [
{
"name": "zhangsan",
"age": "10",
"phone": "11111",
"email": "[email protected]"
},
{
"name": "lisi",
"age": "20",
"phone": "22222",
"email": "[email protected]"
},
...
]
}
開始解析:
//先轉JsonObject
JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();
//再轉JsonArray 加上資料頭
JsonArray jsonArray = jsonObject.getAsJsonArray("user");
Gson gson = new Gson();
ArrayList<UserBean> userBeanList = new ArrayList<>();
//迴圈遍歷
for (JsonElement user : jsonArray) {
//通過反射 得到UserBean.class
UserBean userBean = gson.fromJson(user, new TypeToken<UserBean>() {}.getType());
userBeanList.add(userBean);
}
有資料頭的複雜資料
{
"code": 200,
"msg": "OK",
"user": [
{
"name": "zhangsan",
"age": "10",
"phone": "11111",
"email": "[email protected]"
},
{
"name": "lisi",
"age": "20",
"phone": "22222",
"email": "[email protected]"
},
...
]
}
開始解析:
第一步:根據 JSON 建立 Bean ,注意這裡的 Bean 是返回所有欄位,因為 GSON 能直接解析成 List ,同時把 get/set 省略。
public class ResultBean {
//注意變數名與欄位名一致
private int code;
private String msg;
private List<UserBean> user;
public class UserBean{
private String name ;
private String age;
private String phone;
private String email;
...
}
...
}
注意:這個類中有一個UserBean,也可以定義在外面,可以作為JsonArray解析後存入List中的物件。
//GSON直接解析成物件
ResultBean resultBean = new Gson().fromJson(strByJson,ResultBean.class);
//物件中拿到集合
List<ResultBean.UserBean> userBeanList = resultBean.getUser();