Android:Gson解析 - 從簡單數(shù)據(jù)到復(fù)雜數(shù)據(jù)

Json是一種輕量級的數(shù)據(jù)交換語言,以文字為基礎(chǔ),且易于讓人閱讀和編寫,同時也易于機器解析和生成,因而在客戶端與服務(wù)器交互中得到廣泛應(yīng)用。但Json自帶的解析類用起來卻差強人意,所以市面上因運而生了很多Json轉(zhuǎn)換利器,本文主要介紹其中之一Gson。Gson是google發(fā)布的library,主要為了方便將Java對象序列化Serialization至輕量化的封包格式JSON,提供了很多方便快捷的方法。

通過gradle導(dǎo)入包

登錄網(wǎng)站MVNRepository,在搜索框中搜索gson,即可出現(xiàn)各種不同的版本,選擇gradle下需要的版本,并復(fù)制到gradle文件中即可。

Gson基本用法

Gson提供了兩個方法直接用于解析和生成方法,二者都有重載方法:

  • fromJson():實現(xiàn)反序列化
  • toJson():實現(xiàn)序列化

基本數(shù)據(jù)類型的生成

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不擔(dān)當(dāng)任何特殊的角色,也不實現(xiàn)任何特殊的Java框架的接口。

Gson中的泛型

當(dāng)我們解析Json數(shù)組時,一般有兩種方式:使用數(shù)組,使用List。而List對于增刪都比較方便,所以實際用List較多

數(shù)組
String[] strings = gson.fromJson(jsonArray, String[].class);

但對于List將上面代碼中的 String[].class ,不能直接改為List<String>.class。對于Java來說 List<String>List<User>這兩個字節(jié)碼文件只有一個,就是 List.class,這就是Java泛型使用時要注意的泛型擦除問題。

List

為了解決上述問題,Gson提供TypeToken來實現(xiàn)對泛型的支持。TypeToken 這個類幫助我們捕獲(capture)像 List 這樣的泛型信息。Java編譯器會把捕獲到的泛型信息編譯到這個匿名內(nèi)部類里,然后在運行時就可以被 getType() 方法用反射的 API 提取到。也就是將泛型T轉(zhuǎn)成 .class

List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());

注:TypeToken
的構(gòu)造方法是protected
修飾的,所以上面才會寫成new TypeToken<List<String>>() {}.getType()
而不是new TypeToken<List<String>>().getType()

@Expose、@SerializeName注解的使用

Json解析的字段和值得名稱和類型是一一對應(yīng)的,但有時前端和后臺使用的語言不同,二者語言規(guī)范風(fēng)格不同,命名時常常會出現(xiàn)不和諧的地方。這時 @Expose @SerializeName 兩個注解就要發(fā)揮他們的作用啦

  • @Expose注解:區(qū)分實體中不想被序列化的屬性,其自身包含兩個屬性deserialize(反序列化)和serialize(序列化),默認(rèn)都為true
  • @SerializeName注解:定義屬性序列化后的名稱
    使用 new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();創(chuàng)建Gson對象,沒有@Expose注釋的屬性將不會被序列化.。另外想要不序列化某個屬性,也可以使用transient。

Gson在序列化和反序列化時需要使用反射,說到反射就想到注解,一般各類庫都將注解放到annotations包下,打開源碼在com.google.gson包下有一個annotations類,其中有一個SerializedName的注解類,這就是我們用到的。

Gson解析復(fù)雜Json數(shù)據(jù)

首先,要知道兩個類:
1、JsonParse
從名稱我們就可以看出,這是一個解析類。沒錯,它可以把 JSON 數(shù)據(jù)分別通過getAsJsonObjectgetAsJsonArray解析成JsonObjectJsonArray。這跟普通的解析 JSON 差不多。
2、JsonElement
是一個抽象類,代表 JSON 串中的某一個元素,可以是JsonObject/JsonArray/JsonPrimitive/...中的任何一種元素。

沒有數(shù)據(jù)頭的純數(shù)組

JSON里面只有一個數(shù)組,而數(shù)組中沒有名字:

[
  {
    "name": "zhangsan",
    "age": "10",
    "phone": "11111",
    "email": "11111@11.com"
  },
  {
    "name": "lisi",
    "age": "20",
    "phone": "22222",
    "email": "22222@22.com"
  },
  ...
]

開始解析,首先定義一個用戶類:

public class UserBean {
    //變量名跟JSON數(shù)據(jù)的字段名需要一致
    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());

方法二:傳統(tǒng)老實方法

    //Json的解析類對象
    JsonParser parser = new JsonParser();
    //將JSON的String 轉(zhuǎn)成一個JsonArray對象
    JsonArray jsonArray = parser.parse(strByJson).getAsJsonArray();

    Gson gson = new Gson();
    ArrayList<UserBean> userBeanList = new ArrayList<>();

    //加強for循環(huán)遍歷JsonArray
    for (JsonElement user : jsonArray) {
        //使用GSON,直接轉(zhuǎn)成Bean對象
        UserBean userBean = gson.fromJson(user, UserBean.class);
        userBeanList.add(userBean);
    }
有數(shù)據(jù)頭的純數(shù)組數(shù)據(jù)
{
  "user": [
    {
      "name": "zhangsan",
      "age": "10",
      "phone": "11111",
      "email": "11111@11.com"
    },
    {
      "name": "lisi",
      "age": "20",
      "phone": "22222",
      "email": "22222@22.com"
    },
    ...
  ]
}

開始解析:

    //先轉(zhuǎn)JsonObject
    JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();
    //再轉(zhuǎn)JsonArray 加上數(shù)據(jù)頭
    JsonArray jsonArray = jsonObject.getAsJsonArray("user");

    Gson gson = new Gson();
    ArrayList<UserBean> userBeanList = new ArrayList<>();

    //循環(huán)遍歷
    for (JsonElement user : jsonArray) {
        //通過反射 得到UserBean.class
        UserBean userBean = gson.fromJson(user, new TypeToken<UserBean>() {}.getType());
        userBeanList.add(userBean);
    }
有數(shù)據(jù)頭的復(fù)雜數(shù)據(jù)
{
  "code": 200,
  "msg": "OK",
  "user": [
    {
      "name": "zhangsan",
      "age": "10",
      "phone": "11111",
      "email": "11111@11.com"
    },
    {
      "name": "lisi",
      "age": "20",
      "phone": "22222",
      "email": "22222@22.com"
    },
    ...
  ]
}

開始解析:
第一步:根據(jù) 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();

另外,變量名與字段名不一致也可以,因為Json中字段通常為下劃線方式,而Java中字段通常為駝峰方式,故需要能夠轉(zhuǎn)換對應(yīng),而Gson也有相關(guān)功能,例如:

public class UserBean {
      @SerializeName("user_name")
      private String userName;
      @SerializeName("user_age")
      private String userAge;
}

工具推薦

jsonschema2pojo:根據(jù)JSON結(jié)構(gòu)產(chǎn)生POJO對象

參考資料

Gson User Guide
通透Gson@Expose注解、@SerializedName、解析json數(shù)據(jù)
Android:用GSON 五招之內(nèi)搞定任何JSON數(shù)組
你真的會用Gson嗎?Gson使用指南(一)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.概述2.Gson的目標(biāo)3.Gson的性能和擴展性4.Gson的使用者5.如何使用Gson 通過Maven來使用...
    人失格閱讀 14,545評論 2 18
  • 為了更好的學(xué)習(xí)Gson,特將Gson User Guide翻譯如下。由于本人英文水平有限,如有錯誤,還請指正,謝謝...
    WeberLisper閱讀 7,043評論 0 6
  • 鼻煙壺最早出現(xiàn)于十八世紀(jì)初的中國,對西方及亞洲藏家而言均極具吸引力。此珍貴容器用以盛裝當(dāng)時傳入中土的鼻煙末粉,起初...
    中亞藝術(shù)閱讀 591評論 0 1
  • 收到了小妍的微信,她說她現(xiàn)在不想干了,她的主任處處擠兌她,她和她主任已經(jīng)鬧僵了,她說,心里很煩很不開心,不想再干...
    維漪閱讀 272評論 5 6
  • 鄉(xiāng)愁,是永恒的話題,因為故鄉(xiāng)不僅有山、有水、有草、有樹,有牛羊、有雞鴨,更有年邁的雙親,和,那個她。 因為種種原因...
    噠噠啊dada閱讀 926評論 0 2

友情鏈接更多精彩內(nèi)容