久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

[轉]用GSON 五招之內搞定任何JSON數組

 一本正經地胡鬧 2019-05-27

關于GSON的入門級使用,這里就不提了,,如有需要可以看這篇博文 《Google Gson的使用方法,實現Json結構的相互轉換》 ,,寫的很好,通俗易懂,。

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

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

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

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

開始過招吧,!

第一招 A

沒有數據頭的純數組JSON如何解析,?

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

[
  {
    "name": "zhangsan",
    "age": "10",
    "phone": "11111",
    "email": "[email protected]"
  },
  {
    "name": "lisi",
    "age": "20",
    "phone": "22222",
    "email": "[email protected]"
  },
  ...
]

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

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

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

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

/**
 * 解析沒有數據頭的純數組
 */
private void parseNoHeaderJArray() {
    //拿到本地JSON 并轉成String
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_1);

    //Json的解析類對象
    JsonParser parser = new JsonParser();
    //將JSON的String 轉成一個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,,直接轉成Bean對象
        UserBean userBean = gson.fromJson(user, UserBean.class);
        userBeanList.add(userBean);
    }
    mainLView.setAdapter(new UserAdapter(this, userBeanList));
}

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

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

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

1、JsonParse

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

2,、JsonElement

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

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

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

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

第二招 Q

有數據頭的純數組數據該怎么解析,?

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

{
  "muser": [
    {
      "name": "zhangsan",
      "age": "10",
      "phone": "11111",
      "email": "[email protected]"
    },
    {
      "name": "lisi",
      "age": "20",
      "phone": "22222",
      "email": "[email protected]"
    },
    ...
  ]
}

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

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

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

/**
 * 解析有數據頭的純數組
 */
private void parseHaveHeaderJArray() {
    //拿到本地JSON 并轉成String
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_2);

    //先轉JsonObject
    JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();
    //再轉JsonArray 加上數據頭
    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ā)現它所在的包:

import com.google.gson.reflect.TypeToken;

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

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

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

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

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

第三招 W

有數據頭的復雜數據該如何解析呢,?

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

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

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

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

/**
 * Created by xiarui on 2016/8/30.
 * 返回所有結果的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 ,。 它雖然跟上面第一第二招雖然內容一樣,但是作用不一樣,,這是作為 JsonArray 解析后存入 List 中的對象,。

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

/**
 * 有消息頭 復雜數據 常規(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));
}

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

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

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

第四招 E

只想解析復雜JSON中的數組或數組中的某部分內容怎么辦?

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

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

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

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

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

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

現在來說一下完整的思路,,也是我學習中思考的過程:

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

好了,完整的代碼如下:

/**
 * 有數據頭 復雜數據 截取方式
 */
private void parseComplexJArrayByDirect() {
    //拿到JSON字符串
    String strByJson = JsonToStringUtil.getStringByJson(this, R.raw.juser_3);
    List<UserBean> userBeanList = new ArrayList<>();

    //拿到數組
    JsonObject jsonObject = new JsonParser().parse(strByJson).getAsJsonObject();
    JsonArray jsonArray = jsonObject.getAsJsonArray("muser");

    //循環(huán)遍歷數組
    for (JsonElement user : jsonArray) {
        UserBean userBean = new Gson().fromJson(user, new TypeToken<UserBean>() {
        }.getType());
        //根據條件過濾
        if (Integer.parseInt(userBean.getAge()) > 30) {
            userBeanList.add(userBean);
        }
    }
    mainLView.setAdapter(new UserAdapter(this, userBeanList));
}

運行的結果圖如下:

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

第五招 R

如果一個 JSON 數據很很很復雜怎么解析,?

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

{
  "group": {
    "user": {
      "name": "張三",
      "age": "10",
      "phone": "11111",
      "email": "[email protected]"
    },
    "info": {
      "address": "北京",
      "work": "Android Dev",
      "pay": "10K",
      "motto": "先定一個小目標,,比如我先賺一個億"
    }
  }
}

三種方式解析:

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

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

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

/**
 * 通過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();
}

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

五招過完,,多謝指教!

總結

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

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

參考資料

靈活組裝Json的數據使用Gson的JsonParser和JsonReader解析Json詳解例子

使用Gson解析復雜的json數據 – tkwxty

JsonElement的簡單說明 – chunqiuwei

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

項目源碼

GsonArrayDemo – IamXiaRui – Github

 

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

    本站是提供個人知識管理的網絡存儲空間,所有內容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內容中的聯(lián)系方式,、誘導購買等信息,謹防詐騙,。如發(fā)現有害或侵權內容,,請點擊一鍵舉報。
    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約