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

Json是一種輕量級的數(shù)據(jù)交換語言,以文字為基礎(chǔ),且易于讓人閱讀和編寫铣猩,同時也易于機(jī)器解析和生成,因而在客戶端與服務(wù)器交互中得到廣泛應(yīng)用茴丰。但Json自帶的解析類用起來卻差強(qiáng)人意达皿,所以市面上因運(yùn)而生了很多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():實(shí)現(xiàn)反序列化
  • toJson():實(shí)現(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)任何特殊的角色钟病,也不實(shí)現(xiàn)任何特殊的Java框架的接口。

Gson中的泛型

當(dāng)我們解析Json數(shù)組時刚梭,一般有兩種方式:使用數(shù)組肠阱,使用List。而List對于增刪都比較方便朴读,所以實(shí)際用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來實(shí)現(xiàn)對泛型的支持鉴吹。TypeToken 這個類幫助我們捕獲(capture)像 List 這樣的泛型信息姨伟。Java編譯器會把捕獲到的泛型信息編譯到這個匿名內(nèi)部類里,然后在運(yùn)行時就可以被 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ū)分實(shí)體中不想被序列化的屬性嫩痰,其自身包含兩個屬性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)老實(shí)方法

    //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<>();

    //加強(qiáng)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)系作者
禁止轉(zhuǎn)載排拷,如需轉(zhuǎn)載請通過簡信或評論聯(lián)系作者折汞。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市顷蟆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌腐魂,老刑警劉巖帐偎,帶你破解...
    沈念sama閱讀 211,376評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異蛔屹,居然都是意外死亡削樊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,126評論 2 385
  • 文/潘曉璐 我一進(jìn)店門兔毒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來漫贞,“玉大人,你說我怎么就攤上這事育叁⊙钙辏” “怎么了?”我有些...
    開封第一講書人閱讀 156,966評論 0 347
  • 文/不壞的土叔 我叫張陵豪嗽,是天一觀的道長谴蔑。 經(jīng)常有香客問我,道長昵骤,這世上最難降的妖魔是什么树碱? 我笑而不...
    開封第一講書人閱讀 56,432評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮变秦,結(jié)果婚禮上成榜,老公的妹妹穿的比我還像新娘。我一直安慰自己蹦玫,他們只是感情好赎婚,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,519評論 6 385
  • 文/花漫 我一把揭開白布刘绣。 她就那樣靜靜地躺著,像睡著了一般挣输。 火紅的嫁衣襯著肌膚如雪纬凤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,792評論 1 290
  • 那天撩嚼,我揣著相機(jī)與錄音停士,去河邊找鬼。 笑死完丽,一個胖子當(dāng)著我的面吹牛恋技,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播逻族,決...
    沈念sama閱讀 38,933評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼蜻底,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了聘鳞?” 一聲冷哼從身側(cè)響起薄辅,我...
    開封第一講書人閱讀 37,701評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎抠璃,沒想到半個月后站楚,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,143評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡鸡典,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,488評論 2 327
  • 正文 我和宋清朗相戀三年源请,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片彻况。...
    茶點(diǎn)故事閱讀 38,626評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡谁尸,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出纽甘,到底是詐尸還是另有隱情良蛮,我是刑警寧澤,帶...
    沈念sama閱讀 34,292評論 4 329
  • 正文 年R本政府宣布悍赢,位于F島的核電站决瞳,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏左权。R本人自食惡果不足惜皮胡,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,896評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望赏迟。 院中可真熱鬧屡贺,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,742評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至量没,卻和暖如春玉转,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背殴蹄。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工究抓, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人袭灯。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓漩蟆,卻偏偏與公主長得像,于是被迫代替她去往敵國和親妓蛮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,494評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 1.概述2.Gson的目標(biāo)3.Gson的性能和擴(kuò)展性4.Gson的使用者5.如何使用Gson 通過Maven來使用...
    人失格閱讀 14,222評論 2 18
  • 為了更好的學(xué)習(xí)Gson圾叼,特將Gson User Guide翻譯如下蛤克。由于本人英文水平有限,如有錯誤夷蚊,還請指正构挤,謝謝...
    WeberLisper閱讀 6,770評論 0 6
  • 鼻煙壺最早出現(xiàn)于十八世紀(jì)初的中國,對西方及亞洲藏家而言均極具吸引力惕鼓。此珍貴容器用以盛裝當(dāng)時傳入中土的鼻煙末粉筋现,起初...
    中亞藝術(shù)閱讀 506評論 0 1
  • 收到了小妍的微信,她說她現(xiàn)在不想干了箱歧,她的主任處處擠兌她矾飞,她和她主任已經(jīng)鬧僵了,她說呀邢,心里很煩很不開心洒沦,不想再干...
    悠然晨欣閱讀 241評論 5 6
  • 鄉(xiāng)愁申眼,是永恒的話題,因為故鄉(xiāng)不僅有山蝉衣、有水括尸、有草、有樹病毡,有牛羊濒翻、有雞鴨,更有年邁的雙親,和肴焊,那個她前联。 因為種種原因...
    噠噠啊dada閱讀 710評論 0 2