九色国产,午夜在线视频,新黄色网址,九九色综合,天天做夜夜做久久做狠狠,天天躁夜夜躁狠狠躁2021a,久久不卡一区二区三区

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
[轉(zhuǎn)]用GSON 五招之內(nèi)搞定任何JSON數(shù)組

關(guān)于GSON的入門級使用,這里就不提了,如有需要可以看這篇博文 《Google Gson的使用方法,實現(xiàn)Json結(jié)構(gòu)的相互轉(zhuǎn)換》 ,寫的很好,通俗易懂。

我為什么寫這篇文章呢?因為前幾晚跟好友 xiasuhuei321 探討了一下GSON解析復(fù)雜的JSON的時候,能不能只解析源數(shù)據(jù)中的數(shù)組,甚至只解析數(shù)組的某一部分。探討了二十分鐘,得出結(jié)論:沒用過,不知道。

所以今天特地研究了一下,發(fā)現(xiàn)真的So Easy!之前想復(fù)雜了,學(xué)習(xí)的過程中,發(fā)現(xiàn)有五種方式分別搞定不同情況的JSON數(shù)組,也就是今天說的五大招!

在介紹之前先來個約定,比如下面的這個JSON:

"muser": [    {      "name": "zhangsan",      "age": "10",      "phone": "11111",      "email": "11111@11.com"    },    ...]
  • 這里的 “muser” ,也就是數(shù)組的名稱,稱它為數(shù)據(jù)頭,防止跟里面的 字段 有歧義;
  • 如果沒有數(shù)據(jù)頭,那就叫它純數(shù)據(jù),或者純數(shù)組數(shù)據(jù);
  • 代碼中用到的 JsonArray/JsonObject 等熟悉的類全部來自 GSON 。

開始過招吧!

第一招 A

沒有數(shù)據(jù)頭的純數(shù)組JSON如何解析?

根據(jù)約定,也就是這個 JSON 里面只有一個數(shù)組(JsonArray),而且這個數(shù)組沒有名字,比如像下面這樣的:

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

這里其實是最簡單的一種 JSON 數(shù)組格式,強大的 GSON 可以直接解析成一個 List 。但在這里我先不直接解析,就用比較老實的方法去解析,因為需要引出兩個東西。

首先我們需要建立一個Bean對象,注意變量名要跟字段名稱一致,沒什么好說的:

public class UserBean {    //變量名跟JSON數(shù)據(jù)的字段名需要一致    private String name ;    private String age;    private String phone;    private String email;    ...}

下面這是解析過程,先看代碼:

/** * 解析沒有數(shù)據(jù)頭的純數(shù)組 */private void parseNoHeaderJArray() {    //拿到本地JSON 并轉(zhuǎn)成String    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_1);    //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);    }    mainLView.setAdapter(new UserAdapter(this, userBeanList));}

從代碼中可以看出解析的步驟如下:

  • 無論 JSON 來自本地還是網(wǎng)絡(luò)獲取,都要先將 JSON 轉(zhuǎn)成 String ;
  • 需要一個 JSON 解析類對象將JSON的字符串轉(zhuǎn)成 JsonArray ,前提是我們知道 JSON 中只有純數(shù)組;
  • 循環(huán)遍歷 JsonArray ,并用 GSON 解析成相應(yīng)的對象。

代碼本身不難,容易看懂,但前面說到,這里我故意這樣寫,因為需要說兩個東西:

1、JsonParse

從名稱我們就可以看出,這是一個解析類。沒錯,它可以把 JSON 數(shù)據(jù)分別通過 getAsJsonObject 和 getAsJsonArray 解析成 JsonObject 和 JsonArray 。這跟普通的解析 JSON 差不多,不展開說。

2、JsonElement

這個類我是第一次見,它是一個抽象類,代表 JSON 串中的某一個元素,可以是 JsonObject/JsonArray/JsonPrimitive/… 中的任何一種元素。

所以在上面的代碼中,我們可以看到它能把 JsonArray 中的每一個元素轉(zhuǎn)成 JsonObject ,甚至說它本身就是 JsonObject 。

好了,就為了說這兩個東西。記住,后面將會用到。

來看一下運行的圖吧,很簡單的東西,后面的二三都是這樣的效果,就不重復(fù)貼圖了:

第二招 Q

有數(shù)據(jù)頭的純數(shù)組數(shù)據(jù)該怎么解析?

內(nèi)容跟上面的 JSON 一模一樣,只不過加了一個名稱 “muser” ,也就是約定好的 數(shù)據(jù)頭 :

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

有人說,這還不簡單,在第一招中的 getAsJsonArray 加一個字符串就是咯,就像這樣:

JsonArray jsonArray = parser.parse(strByJson).getAsJsonArray("muser");

思路是對的,但是不要忘了,數(shù)組裝在一個 { } 括起來的 JsonObject 里。還記得上面的 JsonParse 么,它的 getAsJsonObject 可以做到這點,所以代碼就是這樣啦,很簡單就不再解釋了:

/** * 解析有數(shù)據(jù)頭的純數(shù)組 */private void parseHaveHeaderJArray() {    //拿到本地JSON 并轉(zhuǎn)成String    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_2);    //先轉(zhuǎn)JsonObject    JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();    //再轉(zhuǎn)JsonArray 加上數(shù)據(jù)頭    JsonArray jsonArray = jsonObject.getAsJsonArray("muser");    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);    }    mainLView.setAdapter(new UserAdapter(this, userBeanList));}

注意,這里又引出了一個東西: TypeToken ,它是什么呢?

3、TypeToken

這個東西很有意思,本來我不知道到是干嘛的,看了看源碼,看不懂。后來無意發(fā)現(xiàn)它所在的包:

import com.google.gson.reflect.TypeToken;

哎喲我去, reflect 這不是反射么,一下子就明白了。沒錯,它其實是一個匿名內(nèi)部類,看一下官方解釋:

GSON 提供了 TypeToken 這個類來幫助我們捕獲(capture)像 List 這樣的泛型信息。Java編譯器會把捕獲到的泛型信息編譯到這個匿名內(nèi)部類里,然后在運行時就可以被 getType() 方法用反射的 API 提取到。

解釋的很官方,實際上就是一句 通俗但不嚴(yán)謹(jǐn) 的話,它將泛型 T 轉(zhuǎn)成 .class 。比如上面的 TypeToken 經(jīng)過 getType() 后就是 UserBean.class 。

好了,說到這里基本鋪墊就完成了,再次強調(diào)一下:

對于上面的 JSON 完全可以直接通過 GSON 轉(zhuǎn)成 List ,不用這么麻煩,我只是為了引出3個小知識。

第三招 W

有數(shù)據(jù)頭的復(fù)雜數(shù)據(jù)該如何解析呢?

簡單的說完了,鋪墊也鋪完了,來看一看復(fù)雜的吧:

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

這里就不再是純數(shù)組數(shù)據(jù)了,還有兩個湊數(shù)的不知道干嘛用的字段,這里也有數(shù)據(jù)頭,之前用的是笨方法,現(xiàn)在來真正見識一下GSON的威力吧。

第一步根據(jù) JSON 建立 Bean ,注意這里的 Bean 是返回所有字段,因為 GSON 能直接解析成 List ,所以 Bean 是下面這樣的,同樣把占地方的 get/set 省略:

/** * Created by xiarui on 2016/8/30. * 返回所有結(jié)果的Bean */public class ResultBean {    //注意變量名與字段名一致    private int code;    private String msg;    private List<UserBean> muser;    public class UserBean{        private String name ;        private String age;        private String phone;        private String email;        ...    }    ...}

注意,這個 ResultBean 里面有一個 UserBean 。 它雖然跟上面第一第二招雖然內(nèi)容一樣,但是作用不一樣,這是作為 JsonArray 解析后存入 List 中的對象。

算了,有點拗口,直接上代碼吧:

/** * 有消息頭 復(fù)雜數(shù)據(jù) 常規(guī)方式 */private void parseComplexJArrayByCommon() {    //拿到Json字符串    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_3);    //GSON直接解析成對象    ResultBean resultBean = new Gson().fromJson(strByJson,ResultBean.class);    //對象中拿到集合    List<ResultBean.UserBean> userBeanList = resultBean.getMuser();    //展示到UI中    mainLView.setAdapter(new ResultAdapter(this, userBeanList));}

沒錯,就是這么四句話搞定第一二招的內(nèi)容??闯鯣SON的強大了吧,當(dāng)然如果有人想不開只寫一句話的話:

mainLView.setAdapter(new ResultAdapter(this,new Gson().fromJson(JsonToStringUtil.getStringByJson(this,R.raw.juser_3),ResultBean.class).getMuser()));

我也是沒意見的,不過請對自己好一點,謝謝。

第四招 E

只想解析復(fù)雜JSON中的數(shù)組或數(shù)組中的某部分內(nèi)容怎么辦?

好了,來到重點了,這也是跟好友 xiasuhuei321 沒有討論出來的情況。

還是上面的JSON數(shù)據(jù),這里為了篇幅就不貼重復(fù)代碼了,假如我只想取 “muser” 這個數(shù)組中的年齡(age)大于30歲的怎么辦?

OK,當(dāng)然可以先全部解析,再從 List 中取。那假如我有一萬條數(shù)據(jù)呢?全部解析不是很麻煩呢?

所以一個思路就是第一二招中說的: 遍歷!

OK,你會問先遍歷還不是要讀一萬條,是的,還是要讀一萬條,但是假如我要把這些存入數(shù)據(jù)庫呢?假如一萬條數(shù)據(jù)中只有一條符合條件,難道我先存一萬條,再從數(shù)據(jù)庫中查詢么?

當(dāng)然這種情況是極端情況,但也說明了一個問題,不能所有情況下都先全部解析,假如有一萬個字段,Bean還得寫多長…可怕。

現(xiàn)在來說一下完整的思路,也是我學(xué)習(xí)中思考的過程:

  • 第一點肯定就是剛才提到的遍歷,這個很好理解,所以我們先要取這一個數(shù)組(JsonArray),那么如何取呢?還記得之前提到的 JsonParse 么,它的 getAsJsonArray() 可以傳入 數(shù)據(jù)頭 拿到數(shù)組,當(dāng)然不要忘了最外面一層是個 JsonObject 。
    //最外層JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();//需要遍歷的數(shù)組JsonArray jsonArray = jsonObject.getAsJsonArray("muser");
  • 拿到數(shù)組以后,我們就可以遍歷了,經(jīng)過第一二招的洗禮,相信在遍歷上,應(yīng)該沒什么問題了,使用的還是之前提到的 JsonElement 。
    //循環(huán)遍歷數(shù)組for (JsonElement user : jsonArray) {    UserBean userBean = new Gson().fromJson(user, new TypeToken<UserBean>() {}.getType());    //根據(jù)條件過濾    if (Integer.parseInt(userBean.getAge()) > 30) {        userBeanList.add(userBean);    }}
  • 上面的代碼很簡單,也用到了之前提到的 TypeToken ,什么意思就不用解釋了吧。

好了,完整的代碼如下:

/** * 有數(shù)據(jù)頭 復(fù)雜數(shù)據(jù) 截取方式 */private void parseComplexJArrayByDirect() {    //拿到JSON字符串    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_3);    List<UserBean> userBeanList = new ArrayList<>();    //拿到數(shù)組    JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();    JsonArray jsonArray = jsonObject.getAsJsonArray("muser");    //循環(huán)遍歷數(shù)組    for (JsonElement user : jsonArray) {        UserBean userBean = new Gson().fromJson(user, new TypeToken<UserBean>() {        }.getType());        //根據(jù)條件過濾        if (Integer.parseInt(userBean.getAge()) > 30) {            userBeanList.add(userBean);        }    }    mainLView.setAdapter(new UserAdapter(this, userBeanList));}

運行的結(jié)果圖如下:

可以看到,現(xiàn)在我們做到了只取 JSON 數(shù)據(jù)中數(shù)組中某一部分了。那么擴展一下,只取 JSON 數(shù)據(jù)中的某一個數(shù)組中的某一個字段呢?當(dāng)然可以實現(xiàn),不過還是留給大家自己思考吧,當(dāng)然下面反人類的第五招也是可以解決這個問題的。

第五招 R

如果一個 JSON 數(shù)據(jù)很很很復(fù)雜怎么解析?

什么叫做復(fù)雜,這里我簡單寫了個比較復(fù)雜的,有數(shù)據(jù)頭,一層嵌套一層,我還沒有寫數(shù)組呢:

{  "group": {    "user": {      "name": "張三",      "age": "10",      "phone": "11111",      "email": "11111@11.com"    },    "info": {      "address": "北京",      "work": "Android Dev",      "pay": "10K",      "motto": "先定一個小目標(biāo),比如我先賺一個億"    }  }}

三種方式解析:

  • 第三招,全部解析出來;
  • 第四招,要什么解析什么;
  • 第五招,反人類的 JsonReader 。

至于為什么反人類,不好說。大家看代碼就知道了,代碼很簡單,跟 XML 的解析差不多,是根據(jù)節(jié)點來的,至于怎么用,還是那句話直接看代碼吧,確實處理起來邏輯清晰,但是代碼量上,真的不敢恭維。

只貼代碼不作解釋,如想詳細(xì)了解,看文末鏈接。

/** * 通過JsonReader的方式去解析 */private void parseComplexJArrayByReader() throws IOException {    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_4);    JsonReader reader = new JsonReader(new StringReader(strByJson));    try {        reader.beginObject();        String tagName = reader.nextName();        if (tagName.equals("group")) {            //讀group這個節(jié)點            readGroup(reader);        }        reader.endObject();    } finally {        reader.close();    }}/** * 讀group這個節(jié)點 * * @param reader JsonReader */private void readGroup(JsonReader reader) throws IOException {    reader.beginObject();    while (reader.hasNext()) {        String tagName = reader.nextName();        if (tagName.equals("user")) {            readUser(reader);        } else if (tagName.equals("info")) {            readInfo(reader);        }    }    reader.endObject();}/** * 讀用戶基本消息 user節(jié)點 * * @param reader JsonReader */private void readUser(JsonReader reader) throws IOException {    reader.beginObject();    while (reader.hasNext()) {        String tag = reader.nextName();        if (tag.equals("name")) {            String name = reader.nextString();            nameText.setText(name);        } else if (tag.equals("age")) {            String age = reader.nextString();            ageText.setText(age);        }         ...        else {            reader.skipValue();//忽略        }    }    reader.endObject();}/** * 讀用戶其他消息 info節(jié)點 * * @param reader JsonReader */private void readInfo(JsonReader reader) throws IOException {    reader.beginObject();    while (reader.hasNext()) {        String tag = reader.nextName();        if (tag.equals("address")) {            String address = reader.nextString();            addressText.setText(address);        } else if (tag.equals("work")) {            String work = reader.nextString();            workText.setText(work);        }         ...        else {            reader.skipValue();//忽略        }    }    reader.endObject();}

上面代碼有省略,因為好長…運行圖如下:

五招過完,多謝指教!

總結(jié)

以上幾乎就是 JSO N數(shù)組的所有情況了,這五招也幾乎能全部搞定!不得不說,GSON 確實比較強大,強大在于可以將 JSON 直接解析成對象,比以前的手動去解析方便太多,當(dāng)然 fastJson 也能實現(xiàn)這點,但是這東西還是官方的用的順手。

在學(xué)習(xí)的過程中,也是一步一步來的,所以文章也是學(xué)習(xí)的過程,從簡單的例子學(xué)到關(guān)鍵內(nèi)容,再解決復(fù)雜情況。由于文章寫得倉促,如有疑問或錯誤,歡迎交流與指正,謝謝!

參考資料

靈活組裝Json的數(shù)據(jù)使用Gson的JsonParser和JsonReader解析Json詳解例子

使用Gson解析復(fù)雜的json數(shù)據(jù) – tkwxty

JsonElement的簡單說明 – chunqiuwei

Java進階(四)Java反射TypeToken解決泛型運行時類型擦除的有關(guān)問題解決

項目源碼

GsonArrayDemo – IamXiaRui – Github

 

(原文地址:http://www.open-open.com/lib/view/open1472632967912.html)

本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
java創(chuàng)建json數(shù)據(jù),構(gòu)建json數(shù)據(jù)
SpringBoot整合Quartz
josn 工具包
android網(wǎng)絡(luò)編程
android發(fā)送/接收json數(shù)據(jù)
JSON三種數(shù)據(jù)解析方法
更多類似文章 >>
生活服務(wù)
熱點新聞
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服