使用Gson解析複雜的泛型巢狀泛型資料結構
一、Gson
Gson是由Google自家出來的Json解析庫,使用起來相容性方面當然會有很多優勢,而且解析Json資料也很方便,掌握了Gson的一些基本使用之後就可以使用它解析很多複雜的Json資料了。但當我們要解析一個複雜的資料結構時,比如說List<CardBean<E>>
這種,泛型之中還有泛型的陣列結構,就比較麻煩了。下面我會給出一種方案,在此之前我還是先簡單的介紹一下Gson的一些東西,如果懂的大神請直接跳過,直接看第二節。
在使用Gson之前,你需要了解一下 反射 相關的知識和 泛型 相關的知識。
泛型的相關知識請參考我的第一篇:Java泛型(一)——泛型的定義與使用
Gson中的幾個重要物件
JsonParser : 解析器,可以將String型別的Json資料解析成JsonElement元素。
JsonElement: Json的基本物件元素,它的拓展類有:JsonObject、JsonArray、JsonPrimitive。不同的類封裝了不同的方法,以便於更好的呼叫。
JsonObject: Json的物件,類似於Sun裡面的JSONObject,封裝了物件的資訊。
JsonArray: Json的陣列,同樣類似於Sun裡面的JSONArray,封裝了物件陣列資訊(或者子陣列資訊).
JsonPrimitive: Json原始物件,Sun提供的JSON中沒有這個類,這裡它封裝了Java中基本物件。
Gson: Gson物件,用來將程式中定義的物件轉換成String型別的Json格式;同時也可以將String型別的Json格式轉換成我們想要的物件。
TypeToken: 用於提取泛型引數的型別,用於在解析器將Json解析成我們的實際物件時,在提供給反射機制,以便於例項化具體的類別。
Gson解析泛型
使用Gson的時候,我們一般無外乎是將Json格式的字串解析成物件、以及將物件轉化成Json格式以便於傳輸。
它的最基本的兩個方法如下:
toJson(obj,type): 將物件轉化為Json字串
fromJson(obj,type): 將Json字串轉為type對應的物件
上面的使用方法大家都知道,我就不舉例了。
但當我們使用Gson去解析泛型的時候,我目前就遇到兩個問題:
問題:
解析出來的泛型物件是一個LinkedTreeMap,這個問題比較普遍,解決方法也比較簡單。是因為使用fromJson的時候沒有給泛型類別新增Type說明,例項下面程式碼附上。
/**
* 第一種,沒有在將型別的泛型Type傳入,則得到的泛型物件是一個LinkedTreeMap
*/
public static void test1() {
CardBean<CardBean1000> cardBean = new CardBean<>();
cardBean.cardViewType = 1000;
CardBean1000 cardBean1000 = new CardBean1000();
cardBean1000.agenda = "男";
cardBean1000.name = "張三";
cardBean.data = cardBean1000;
String jsonStr = gson.toJson(cardBean);
System.out.println(jsonStr);
CardBean transCard = gson.fromJson(jsonStr, cardBean.getClass());
System.out.println(transCard.data.getClass().getName());
}
/**
* 第二種,將含有泛型具體的類別Type資訊傳入,則將能夠轉為具體的類別。
*/
public static void test2() {
CardBean<CardBean1000> cardBean = new CardBean<>();
cardBean.cardViewType = 1000;
CardBean1000 cardBean1000 = new CardBean1000();
cardBean1000.agenda = "男";
cardBean1000.name = "張三";
cardBean.data = cardBean1000;
Type type = new TypeToken<CardBean<CardBean1000>>() {
}.getType();
String jsonStr = gson.toJson(cardBean);
System.out.println(jsonStr);
CardBean transCard = gson.fromJson(jsonStr, type);
System.out.println(transCard.data.getClass().getName());
;
}
程式結果對比:
test1——將物件轉化成Json格式: {"data":{"name":"張三","agenda":"男"},"cardViewType":1000}
test1——沒有傳入泛型類別: com.google.gson.internal.LinkedTreeMap
test2——傳入泛型類別: main.Test$CardBean1000
將物件轉化成Json格式並沒有什麼大問題,在test1中沒有傳入泛型的Type類別,因此解析器解析的時候沒有辦法確定泛型的型別,框架中預設將KV形式的Json儲存在了LinkedTreeMap中,將其賦值給了泛型 T,我們只要使用TypeToken將泛型資訊給提取出來,那麼解析器解析的時候就可以具體知道類別(Class),便可以用反射來例項化物件了。
二、Gson解析巢狀泛型陣列
當我們伺服器返回的Json陣列中的物件不同時,就會出現解析List<CardBean<E>>
這樣的巢狀泛型陣列問題。
解析方案
解析上述型別的時候,我們直接使用fromJson(json,Type)
,是無法一步到位的,我們只能拿到一個List<CardBean>
的陣列列表,但CardBean<T>
的泛型我們並沒有解析,實際上也無法解析,因為裡面是什麼樣的物件我們是不知道的,我們也無法確定陣列中的某一個位置是什麼樣的型別。同樣類似於上面的問題,Gson會把CardBean 中的 T 解析成一個LinkedTreeMap,第一次解析我們只能拿到這個資訊,我們如何知道里面的json物件是對應的那一個類呢?我們使用資料結構的方法解決這個問題,這裡我們可以在CardBean物件裡增加一個type欄位,該type與具體的類有一個對映關係(可以儲存在HashMap中,也可以使用列舉)。
說到這裡,很多人應該知道我的思路了,就是我自己做一次解析,取得CardBean裡面的type欄位,再通過對映關係找到對應的class,然後通過反射解析該物件。通過這樣的方式我們就可以達到解析複雜巢狀泛型的目的了,這裡是兩層,多層的話可以使用遞迴方式,或者迴圈的方式解決 。
說了那麼多,show me the code! 附上程式碼吧:
public static void cardViewTypeParse() {
CardBean<CardBean1000> cardBean = new CardBean<>();
CardBean1000 cardBean1000 = new CardBean1000();
cardBean1000.agenda = "女";
cardBean1000.name = "何小蘭";
cardBean.data = cardBean1000;
cardBean.cardViewType = 1000;
CardBean<CardBean1001> cardBean1 = new CardBean<>();
CardBean1001 cardBean1001 = new CardBean1001();
cardBean1001.agenda = "男";
cardBean1001.name = "景曉明";
Extra extra = new Extra();
extra.extra = "extra";
cardBean1001.extra = extra;
cardBean1.data = cardBean1001;
cardBean1.cardViewType = 1001;
JsonArray jArray = new JsonArray();
JsonObject jObject = new JsonObject();
// TODO toJson(Object src,Type typeOfSrc)具體用來幹嘛?有沒有感覺都沒什麼區別,大神指導一下
jArray.add(parser.parse(gson.toJson(cardBean, cardBean.getClass())));
jArray.add(parser.parse(gson.toJson(cardBean1, cardBean1.getClass())));
System.out.println(jArray.toString());
List<CardBean> list0 = gson.fromJson(jArray.toString(), new TypeToken<List<CardBean>>() {
}.getType());
for (CardBean cardBean2 : list0) {
System.out.println(cardBean2.cardViewType);
CardViewType cardViewType = CardViewType.getCardViewType(cardBean2.cardViewType);
CardBeanClient cardBeanClient = new CardBeanClient<>();
cardBeanClient.cardViewType = cardViewType;
cardBeanClient.data = gson.fromJson(gson.toJson(cardBean2.data), cardViewType.clazz);
System.out.println(cardBeanClient.data.toString());
if (cardBean2.data instanceof Map) {
System.out.println(((Map) cardBean2.data).get("name"));
}
}
}
/**
* Client端的Bean包裝類
* @author David
*
* @param <T>
*/
public static class CardBeanClient<T> {
T data;
CardViewType cardViewType;
}
/**
* Server端的Bean包裝類
* @author David
*
* @param <T>
*/
public static class CardBeanServer<T> {
T data;
int cardViewType;
@Override
public String toString() {
// TODO Auto-generated method stub
return data.toString() + " " + cardViewType;
}
}
/**
* 列舉:type與class的對映關係
*/
public enum CardViewType {
CardViewType1000(1000, CardBean1000.class), CardViewType1001(1001, CardBean1001.class);
int type;
Class clazz;
CardViewType(int type, Class clazz) {
this.type = type;
this.clazz = clazz;
}
// 通過value獲取對應的列舉物件
public static CardViewType getCardViewType(int value) {
for (CardViewType cardViewType : CardViewType.values()) {
if (value == cardViewType.type) {
return cardViewType;
}
}
return null;
}
}
/**
* 具體的Bean資料
*/
public static class CardBean1000 {
String name;
String agenda;
@Override
public String toString() {
// TODO Auto-generated method stub
return name + " " + agenda;
}
}
public static class CardBean1001 {
String name;
String agenda;
Extra extra;
@Override
public String toString() {
// TODO Auto-generated method stub
return name + " " + agenda + " " + extra.extra;
}
}
public static class Extra {
String extra;
}
結果列印:
json:[{"data":{"name":"何小蘭","agenda":"女"},"cardViewType":1000},{"data":{"name":"景曉明","agenda":"男","extra":{"extra":"extra"}},"cardViewType":1001}]
1000
type = CardViewType1000 main.Test$CardBean1000
1001
type = CardViewType1001 main.Test$CardBean1001
相關推薦
使用Gson解析複雜的泛型巢狀泛型資料結構
一、Gson Gson是由Google自家出來的Json解析庫,使用起來相容性方面當然會有很多優勢,而且解析Json資料也很方便,掌握了Gson的一些基本使用之後就可以使用它解析很多複雜的Json資料了。但當我們要解析一個複雜的資料結構時,比如說List<
泛型陣列+泛型巢狀+泛型應用例項
泛型陣列 使用泛型方法時,也可以傳遞和返回一個泛型陣列。 【接收和返回泛型陣列】 @SuppressWarnings("unchecked") public class GeneriseDemo30 { public static void
Gson和fastJson 解析巢狀泛型的json資料
Test /* * { "code": 1, "datas": [{ "address": "深圳",
fastjson解析巢狀泛型
/** * author zoush * CreateTime 2017-06-03 16:01 * 直接上虛擬碼 */ public class Outer<T> {
使用swagger-bootstarap-ui 響應類3層巢狀泛型顯示的坑
正常一個分頁查詢的介面返回格式應該是 返回 資料統一的封裝類<分頁資料<要展示的資料類>> 得到的也就是一個3層巢狀2層泛型的資料結構! 也就是這樣 其實也就是 PageHelper 提供的 pageInfo 資訊的複製 加上sw
java 泛型詳解(普通泛型、 萬用字元、 泛型介面,泛型陣列,泛型方法,泛型巢狀)
JDK1.5 令我們期待很久,可是當他釋出的時候卻更換版本號為5.0。這說明Java已經有大幅度的變化。本文將講解JDK5.0支援的新功能-----Java的泛型. 1、Java泛型 其實Java
Java泛型--泛型應用--泛型介面、泛型方法、泛型陣列、泛型巢狀
1、泛型介面 1.1泛型介面的基本概念 1.2泛型介面實現的兩種方式 定義子類:在子類的定義上也宣告泛型型別 interface Info<T>{ // 在介面上定義泛型 pub
Java泛型巢狀示例
/* * 泛型巢狀例項 * date: 2012-10-22 * author: Alex Hohh */ // 泛型類Info<K,V> class Info<K,V>{
利用Gson解析多層巢狀的JSON資料
資料例項: { "error": 0, "status": "success", "results": [ { "currentCity
Gson解析巢狀JSON格式資料
來源說明: 最近在無聊,剛剛又想學一下安卓的APP, 剛剛好看到"中國天氣網"那裡面的有免費的API.剛剛好又想到用GSON解析,我學了一下. 1.資料格式 { "user":"
如何重構多重巢狀“箭頭型”程式碼
本文轉載自 酷 殼 – CoolShell 陳皓。 所謂箭頭型程式碼,基本上來說就是下面這個圖片所示的情況。 那麼,這樣“箭頭型”的程式碼有什麼問題呢?看上去也挺好看的,有對稱美。但是…… 關於箭頭型程式碼的問題有如下幾個: 1)我的顯示器不夠寬,箭頭型程式碼縮排太狠了,需
使用GSON解析複雜資料——天氣資訊
最近在做自己的App時,要在主介面上新增簡單的天氣資訊顯示,然後就理所當然的跑到百度查詢如何才能獲取到天氣資訊,最後決定採用第三方天氣資訊服務商提供的資料,在看第三方提供的API說明時發現,獲取到的天氣資料是Json格式的,需要自己解析。又是經過一番百度,最後確定使用Google
使用Gson解析複雜的json資料
我們app介面資料返回通常是以下格式: {“code”:“0000”,“data”: {“code”:“0002”,“resultData”:null,“resultMsg”:“使用者Token過期,請重新登入”,“error”:[],“msg”:""} 把以上的json資料放線上J
Gson解析複雜Json資料
implementation'com.google.code.gson:gson:2.8.0' 然後根據api獲取到的json資料 { "status": "1", "info": "OK", "infocode": "10000",
手把手教你怎麼解析多層巢狀的JSON資料(使用JSONModel)
使用API API介紹 參考的JSON資料(可能與你看到的不同) { "date": "20181020", "stories": [ { "title": "每週一吸 · 狸花貓",
GSON解析複雜的JSON陣列
1.GSON的兩個重要方法 在GSON的API中,提供了兩個重要的方法:toJson()和fromJson()方法。其中,toJson()方法用來實現將Java物件轉換為相應的JSON資料,fromJson()方法則用來實現將JSON資料轉換為相應的Jav
Gson使用及多層巢狀 json 定義類
問題描述 對於簡單的Json資料,其對應的java bean 也比較簡單,尤其用GSON處理的時候。 但是如果是多層巢狀的json資料,如果是手工用JSONArray和JSONObject進行解析,還是可以的,雖然會繁瑣一點。但是如果用GSON開源庫解析,有
用Gson解析複雜的Json字串
前提:自行將Gson開源庫匯入到工程中(不會的,請自行百度)。 這是本人第一次寫部落格,如有錯誤,請您見諒,也歡迎與我交流! 需要解析的Json字串為: { "error_code": 0, "reason"
Gson Object與json轉換 巢狀物件
解決問題 正確: { "data":{accesstoken : "odA5niNeOhhi1cIK0eOGhrxCB7ClG9R4gl%2Fa2%2FNcOaJ42tWayXKZZZBgIPsh1tRLshlxWyXlEyY...", expirein :"2017-11
通過GSON解析複雜json資料(二)
這裡我們依舊用上文中的 json 字串 , 由於轉換為 map 依舊需要 javaBean , 所有我們的實體物件也不發生改變 這裡我們需要活用 java 反射和型別對比實現需求 先看程式碼 package com.jacx.test.test01.