新聞中心
JSON是一種輕量級的數(shù)據(jù)交換格式,簡潔和清晰的層次結(jié)構(gòu)使得 JSON 成為理想的數(shù)據(jù)交換語言,常被用于實(shí)際項(xiàng)目中。Java生態(tài)圈中有很多處理JSON格式化的類庫,如json-lib框架、Jackson、Google的Gson、阿里的FastJson等,通過這些類庫可以使我們更加簡便地處理JSON。下面本文主要通過一個實(shí)際案例討論分析在解析JSON字符串的過程中遇到泛型該如何處理。

在網(wǎng)站設(shè)計、網(wǎng)站制作中從網(wǎng)站色彩、結(jié)構(gòu)布局、欄目設(shè)置、關(guān)鍵詞群組等細(xì)微處著手,突出企業(yè)的產(chǎn)品/服務(wù)/品牌,幫助企業(yè)鎖定精準(zhǔn)用戶,提高在線咨詢和轉(zhuǎn)化,使成都網(wǎng)站營銷成為有效果、有回報的無錫營銷推廣。創(chuàng)新互聯(lián)建站專業(yè)成都網(wǎng)站建設(shè)十年了,客戶滿意度97.8%,歡迎成都創(chuàng)新互聯(lián)客戶聯(lián)系。
- 案例描述
- 問題引出
- 處理方案
- 原理分析
一、案例描述
首先介紹三個類,為了便于理解將代碼省去非關(guān)鍵部分。
- PrepCommonResp 是一個通用響應(yīng)類,為了支持多種返回類型,設(shè)置了其中一個屬性result為泛型。
- public class PrepCommonResp
{ - private T result; //獲取調(diào)用返回值
- private String code = "000000"; //獲取錯誤碼
- private String msg = "Success";
- //這里省略getter setter等
- }
- public class LeaderboardResp implements Serializable {
- List
leaderboardList; - //這里省略getter setter等
- }
- public class LeaderboardPojo {
- //基本屬性
- }
需求:將一個JSON字符串的String類型數(shù)據(jù)解析到指定了泛型的通用響應(yīng)類實(shí)例PrepCommonResp 對象中。
二、問題引出
一開始編寫時,采用了Jackson的ObjectMapper類readValue方法來進(jìn)行解析,具體代碼如下。
- ObjectMapper mapper = new ObjectMapper();
- PrepCommonResp
resp = mapper.readValue(result,PrepCommonResp.class);
我們期待的結(jié)果是JSON字符串被正確解析,并且result屬性的值是以指定泛型LeaderboardResp的格式存儲。但是通過斷點(diǎn)之后我們發(fā)現(xiàn)result屬性的值是以LinkedHashMap的形式存儲,與期望結(jié)果不符。
三、解決方案
在分析原因之前,先來說說解決方式。解決方式有多種,我們通過了嘗試對比了各種方案之后選擇了其中一種較為簡便的就是采用Gson的fromJson方法來解決,具體代碼如下:
- //嘗試使用Gson
- Gson gson = new Gson();
- PrepCommonResp
resp = gson.fromJson(result, new TypeToken >(){}.getType()); - List
list = resp.getResult().getLeaderboardList();
運(yùn)行結(jié)果如下,result的值以我們期望的LeaderboardResp形式存儲
四、原理分析
1. 先理解泛型與編譯器虛擬機(jī)的關(guān)系以及什么是擦除?
解析: Java語言的泛型基本上是在編譯器中實(shí)現(xiàn)的。由編譯器執(zhí)行類型檢測和推斷后生成普通的非泛型的字節(jié),虛擬機(jī)是完全無感知泛型存在的,這種實(shí)現(xiàn)技術(shù)稱為擦除。編譯器使用泛型類型信息保證類型安全,然后在生成字節(jié)碼之前將其清除。
2. 為什么使用Jackson的readValue方法解析JSON字符串后result的屬性值會是LinkedHashMap而不是我們指定的LeaderboardResp呢?
解析:泛型只在編譯期間起到檢測作用,當(dāng)編譯器將泛型類編譯完成之后,泛型類的類型參數(shù)都被全部擦除。接下來在運(yùn)行期間虛擬機(jī)并不知道泛型的存在,當(dāng)對JSON字符串進(jìn)行解析時由于泛型被擦除了導(dǎo)致虛擬機(jī)并不知道要將其解析成哪種類型,所以就解析為了默認(rèn)的LinkedHashMap類型,導(dǎo)致出現(xiàn)了上面的場景。
3. 那Gson是如何解決泛型擦除這種情況呢?
我們來看看這一句核心代碼
- PrepCommonResp
resp = gson.fromJson(result, new TypeToken >(){}.getType());
解析:Gson的做法非常巧妙,如上面的代碼所示,將需要獲取類型的泛型類作為TypeToken的泛型參數(shù)構(gòu)造一個匿名的子類,然后通過getType()方法就可以獲取到我們想要的泛型類的泛型參數(shù)類型??梢岳斫鉃槭菍⒎盒皖愋痛嫫饋?,解決了泛型擦除的問題。
五、最后
感謝您的閱讀,如果喜歡本文歡迎關(guān)注和轉(zhuǎn)發(fā),本頭條號將持續(xù)分享IT技術(shù)知識。對于文章內(nèi)容有其他想法或意見建議等,歡迎提出共同討論共同進(jìn)步。如果您對于此場景有更好的解決方案也歡迎提出討論。
名稱欄目:當(dāng)JSON解析遇上了泛型,該如何處理泛型擦除問題
文章URL:http://www.fisionsoft.com.cn/article/dpieogh.html


咨詢
建站咨詢
