自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

別了,阿里巴巴fastjson!企業(yè)項(xiàng)目遷移Gson全攻略

開(kāi)發(fā) 架構(gòu)
文章的前半部分,我會(huì)簡(jiǎn)單分析各種json解析框架的優(yōu)劣,并給出企業(yè)級(jí)項(xiàng)目遷移json框架的幾種解決方案。在文章的后半部分,我會(huì)結(jié)合這一個(gè)月的經(jīng)驗(yàn),總結(jié)下Gson的使用問(wèn)題,以及fastjson遷移到Gson踩過(guò)的深坑。

前言

大家好,又雙叒叕見(jiàn)面了,我是天天放大家鴿子的蠻三刀。

在被大家取關(guān)之前,我立下一個(gè)“遠(yuǎn)大的理想”,一定要在這周更新文章?,F(xiàn)在看來(lái),flag有用了。。。

本篇文章是我這一個(gè)多月來(lái)幫助組內(nèi)廢棄fastjson框架的總結(jié),我們將大部分Java倉(cāng)庫(kù)從fastjson遷移至了Gson。

這么做的主要的原因是公司受夠了fastjson頻繁的安全漏洞問(wèn)題,每一次出現(xiàn)漏洞都要推一次全公司的fastjson強(qiáng)制版本升級(jí),很令公司頭疼。

文章的前半部分,我會(huì)簡(jiǎn)單分析各種json解析框架的優(yōu)劣,并給出企業(yè)級(jí)項(xiàng)目遷移json框架的幾種解決方案。

在文章的后半部分,我會(huì)結(jié)合這一個(gè)月的經(jīng)驗(yàn),總結(jié)下Gson的使用問(wèn)題,以及fastjson遷移到Gson踩過(guò)的深坑。

[[376285]]

文章目錄:

  • 為何要放棄fastjson?
  • fastjson替代方案 三種json框架的特點(diǎn)性能對(duì)比最終選擇方案
  • 替換依賴時(shí)的注意事項(xiàng) 謹(jǐn)慎,謹(jǐn)慎,再謹(jǐn)慎做好開(kāi)發(fā)團(tuán)隊(duì)和測(cè)試團(tuán)隊(duì)的溝通做好回歸/接口測(cè)試考慮遷移前后的性能差異
  • 使用Gson替換fastjson Json反序列化范型處理List/Map寫入駝峰與下劃線轉(zhuǎn)換
  • 遷移常見(jiàn)問(wèn)題踩坑 Date序列化方式不同SpringBoot異常Swagger異常@Mapping JsonObject作為入?yún)惓?/li>

注意:是否使用fastjson是近年來(lái)一個(gè)爭(zhēng)議性很大的話題,本文無(wú)意討論框架選型的對(duì)錯(cuò),只關(guān)注遷移這件事中遇到的問(wèn)題進(jìn)行反思和思考。大家如果有想發(fā)表的看法,可以在評(píng)論區(qū) 理 性 討論。

為何要放棄fastjson?

究其原因,是fastjson漏洞頻發(fā),導(dǎo)致了公司內(nèi)部需要頻繁的督促各業(yè)務(wù)線升級(jí)fastjson版本,來(lái)防止安全問(wèn)題。

fastjson在2020年頻繁暴露安全漏洞,此漏洞可以繞過(guò)autoType開(kāi)關(guān)來(lái)實(shí)現(xiàn)反序列化遠(yuǎn)程代碼執(zhí)行并獲取服務(wù)器訪問(wèn)權(quán)限。

從2019年7月份發(fā)布的v1.2.59一直到2020年6月份發(fā)布的 v1.2.71 ,每個(gè)版本的升級(jí)中都有關(guān)于AutoType的升級(jí),涉及13個(gè)正式版本。

fastjson中與AutoType相關(guān)的版本歷史:

  • 1.2.59發(fā)布,增強(qiáng)AutoType打開(kāi)時(shí)的安全性 fastjson
  • 1.2.60發(fā)布,增加了AutoType黑名單,修復(fù)拒絕服務(wù)安全問(wèn)題 fastjson
  • 1.2.61發(fā)布,增加AutoType安全黑名單 fastjson
  • 1.2.62發(fā)布,增加AutoType黑名單、增強(qiáng)日期反序列化和JSONPath fastjson
  • 1.2.66發(fā)布,Bug修復(fù)安全加固,并且做安全加固,補(bǔ)充了AutoType黑名單 fastjson
  • 1.2.67發(fā)布,Bug修復(fù)安全加固,補(bǔ)充了AutoType黑名單 fastjson
  • 1.2.68發(fā)布,支持GEOJSON,補(bǔ)充了AutoType黑名單
  • 1.2.69發(fā)布,修復(fù)新發(fā)現(xiàn)高危AutoType開(kāi)關(guān)繞過(guò)安全漏洞,補(bǔ)充了AutoType黑名單
  • 1.2.70發(fā)布,提升兼容性,補(bǔ)充了AutoType黑名單
  • 1.2.71發(fā)布,補(bǔ)充安全黑名單,無(wú)新增利用,預(yù)防性補(bǔ)充

相比之下,其他的json框架,如Gson和Jackson,漏洞數(shù)量少很多,高危漏洞也比較少,這是公司想要替換框架的主要原因。

fastjson替代方案

本文主要討論Gson替換fastjson框架的實(shí)戰(zhàn)問(wèn)題,所以在這里不展開(kāi)詳細(xì)討論各種json框架的優(yōu)劣,只給出結(jié)論。

經(jīng)過(guò)評(píng)估,主要有Jackson和Gson兩種json框架放入考慮范圍內(nèi),與fastjson進(jìn)行對(duì)比。

三種json框架的特點(diǎn)

FastJson

速度快

fastjson相對(duì)其他JSON庫(kù)的特點(diǎn)是快,從2011年fastjson發(fā)布1.1.x版本之后,其性能從未被其他Java實(shí)現(xiàn)的JSON庫(kù)超越。

使用廣泛

fastjson在阿里巴巴大規(guī)模使用,在數(shù)萬(wàn)臺(tái)服務(wù)器上部署,fastjson在業(yè)界被廣泛接受。在2012年被開(kāi)源中國(guó)評(píng)選為最受歡迎的國(guó)產(chǎn)開(kāi)源軟件之一。

測(cè)試完備

fastjson有非常多的testcase,在1.2.11版本中,testcase超過(guò)3321個(gè)。每次發(fā)布都會(huì)進(jìn)行回歸測(cè)試,保證質(zhì)量穩(wěn)定。

使用簡(jiǎn)單

fastjson的API十分簡(jiǎn)潔。

Jackson

  • 容易使用 - jackson API提供了一個(gè)高層次外觀,以簡(jiǎn)化常用的用例。
  • 無(wú)需創(chuàng)建映射 - API提供了默認(rèn)的映射大部分對(duì)象序列化。
  • 性能高 - 快速,低內(nèi)存占用,適合大型對(duì)象圖表或系統(tǒng)。
  • 干凈的JSON - jackson創(chuàng)建一個(gè)干凈和緊湊的JSON結(jié)果,這是讓人很容易閱讀。

不依賴 - 庫(kù)不需要任何其他的庫(kù),除了JDK。

Gson

  • 提供一種機(jī)制,使得將Java對(duì)象轉(zhuǎn)換為JSON或相反如使用toString()以及構(gòu)造器(工廠方法)一樣簡(jiǎn)單。
  • 允許預(yù)先存在的不可變的對(duì)象轉(zhuǎn)換為JSON或與之相反。
  • 允許自定義對(duì)象的表現(xiàn)形式
  • 支持任意復(fù)雜的對(duì)象
  • 輸出輕量易讀的JSON

性能對(duì)比

本文不詳細(xì)討論性能的差異,畢竟這其中涉及了很多各個(gè)框架的實(shí)現(xiàn)思路和優(yōu)化,所以只給出結(jié)論:

  1. 序列化單對(duì)象性能Fastjson > Jackson > Gson,其中Fastjson和Jackson性能差距很小,Gson性能較差
  2. 序列化大對(duì)象性能Jackson> Fastjson > Gson ,序列化大Json對(duì)象時(shí)Jackson> Gson > Fastjson,Jackson序列化大數(shù)據(jù)時(shí)性能優(yōu)勢(shì)明顯
  3. 反序列化單對(duì)象性能 Fastjson > Jackson > Gson , 性能差距較小
  4. 反序列化大對(duì)象性能 Fastjson > Jackson > Gson , 性能差距較很小

最終選擇方案

Jackson適用于高性能場(chǎng)景,Gson適用于高安全性場(chǎng)景

對(duì)于新項(xiàng)目倉(cāng)庫(kù),不再使用fastjson。對(duì)于存量系統(tǒng),考慮到Json更換成本,由以下幾種方案可選: 項(xiàng)目未使用autoType功能,建議直接切換為非fastjson,如果切換成本較大,可以考慮繼續(xù)使用fastjson,關(guān)閉safemode。業(yè)務(wù)使用了autoType功能,建議推進(jìn)廢棄fastjson。

替換依賴注意事項(xiàng)

企業(yè)項(xiàng)目或者說(shuō)大型項(xiàng)目的特點(diǎn):

  • 代碼結(jié)構(gòu)復(fù)雜,團(tuán)隊(duì)多人維護(hù)。
  • 承擔(dān)重要線上業(yè)務(wù),一旦出現(xiàn)嚴(yán)重bug會(huì)導(dǎo)致重大事故。
  • 如果是老項(xiàng)目,可能缺少文檔,不能隨意修改,牽一發(fā)而動(dòng)全身。
  • 項(xiàng)目有很多開(kāi)發(fā)分支,不斷在迭代上線。

所以對(duì)于大型項(xiàng)目,想要做到將底層的fastjson遷移到gson是一件復(fù)雜且痛苦的事情,其實(shí)對(duì)于其他依賴的替換,也都一樣。

我總結(jié)了如下幾個(gè)在替換項(xiàng)目依賴過(guò)程中要特別重視的問(wèn)題。

謹(jǐn)慎,謹(jǐn)慎,再謹(jǐn)慎

再怎么謹(jǐn)慎都不為過(guò),如果你要更改的項(xiàng)目是非常重要的業(yè)務(wù),那么一旦犯下錯(cuò)誤,代價(jià)是非常大的。并且,對(duì)于業(yè)務(wù)方和產(chǎn)品團(tuán)隊(duì)來(lái)說(shuō),沒(méi)有新的功能上線,但是系統(tǒng)卻炸了,是一件“無(wú)法忍受”的事情。盡管你可能覺(jué)得很委屈,因?yàn)橹挥心慊蛘吣愕膱F(tuán)隊(duì)知道,雖然業(yè)務(wù)看上去沒(méi)變化,但是代碼底層已經(jīng)發(fā)生了翻天覆地的變化。

所以,謹(jǐn)慎點(diǎn)!

做好開(kāi)發(fā)團(tuán)隊(duì)和測(cè)試團(tuán)隊(duì)的溝通

在依賴替換的過(guò)程中,需要做好項(xiàng)目的規(guī)劃,比如分模塊替換,嚴(yán)格細(xì)分排期。

把前期規(guī)劃做好,開(kāi)發(fā)和測(cè)試才能有條不紊的進(jìn)行工作。

開(kāi)發(fā)之間,需要提前溝通好開(kāi)發(fā)注意事項(xiàng),比如依賴版本問(wèn)題,防止由多個(gè)開(kāi)發(fā)同時(shí)修改代碼,最后發(fā)現(xiàn)使用的版本不同,接口用法都不同這種很尷尬,并且要花額外時(shí)間處理的事情。

而對(duì)于測(cè)試,更要事先溝通好。一般來(lái)說(shuō),測(cè)試不會(huì)太在意這種對(duì)于業(yè)務(wù)沒(méi)有變化的技術(shù)項(xiàng)目,因?yàn)榧炔皇莾?yōu)化速度,也不是新功能。但其實(shí)遷移涉及到了底層,很容易就出現(xiàn)BUG。要讓測(cè)試團(tuán)隊(duì)了解更換項(xiàng)目依賴,是需要大量的測(cè)試時(shí)間投入的,成本不亞于新功能,讓他們盡量重視起來(lái)。

做好回歸/接口測(cè)試

上面說(shuō)到測(cè)試團(tuán)隊(duì)需要投入大量工時(shí),這些工時(shí)主要都用在項(xiàng)目功能的整體回歸上,也就是回歸測(cè)試。

當(dāng)然,不只是業(yè)務(wù)回歸測(cè)試,如果有條件的話,要做接口回歸測(cè)試。

如果公司有接口管理平臺(tái),那么可以極大提高這種項(xiàng)目測(cè)試的效率。

打個(gè)比方,在一個(gè)模塊修改完成后,在測(cè)試環(huán)境(或者沙箱環(huán)境),部署一個(gè)線上版本,部署一個(gè)修改后的版本,直接將接口返回?cái)?shù)據(jù)進(jìn)行對(duì)比。一般來(lái)說(shuō)是Json對(duì)比,網(wǎng)上也有很多的Json對(duì)比工具:

  • https://www.sojson.com/

考慮遷移前后的性能差異

正如上面描述的Gson和Fastjson性能對(duì)比,替換框架需要注意框架之間的性能差異,尤其是對(duì)于流量業(yè)務(wù),也就是高并發(fā)項(xiàng)目,響應(yīng)時(shí)間如果發(fā)生很大的變化會(huì)引起上下游的注意,導(dǎo)致一些額外的后果。

使用Gson替換Fastjson

這里總結(jié)了兩種json框架常用的方法,貼出詳細(xì)的代碼示例,幫助大家快速的上手Gson,無(wú)縫切換!

Json反序列化

 

  1. String jsonCase = "[{\"id\":10001,\"date\":1609316794600,\"name\":\"小明\"},{\"id\":10002,\"date\":1609316794600,\"name\":\"小李\"}]"
  2.  
  3. // fastjson 
  4. JSONArray jsonArray = JSON.parseArray(jsonCase); 
  5. System.out.println(jsonArray); 
  6. System.out.println(jsonArray.getJSONObject(0).getString("name")); 
  7. System.out.println(jsonArray.getJSONObject(1).getString("name")); 
  8. // 輸出: 
  9. // [{"date":1609316794600,"name":"小明","id":10001},{"date":1609316794600,"name":"小李","id":10002}] 
  10. // 小明 
  11. // 小李 
  12.  
  13. // Gson 
  14. JsonArray jsonArrayGson = gson.fromJson(jsonCase, JsonArray.class); 
  15. System.out.println(jsonArrayGson); 
  16. System.out.println(jsonArrayGson.get(0).getAsJsonObject().get("name").getAsString()); 
  17. System.out.println(jsonArrayGson.get(1).getAsJsonObject().get("name").getAsString()); 
  18. // 輸出: 
  19. // [{"id":10001,"date":1609316794600,"name":"小明"},{"id":10002,"date":1609316794600,"name":"小李"}] 
  20. // 小明 
  21. // 小李 

看得出,兩者區(qū)別主要在get各種類型上,Gson調(diào)用方法有所改變,但是變化不大。

那么,來(lái)看下空對(duì)象反序列化會(huì)不會(huì)出現(xiàn)異常:

 

  1. String jsonObjectEmptyCase = "{}"
  2.  
  3. // fastjson 
  4. JSONObject jsonObjectEmpty = JSON.parseObject(jsonObjectEmptyCase); 
  5. System.out.println(jsonObjectEmpty); 
  6. System.out.println(jsonObjectEmpty.size()); 
  7. // 輸出: 
  8. // {} 
  9. // 0 
  10.  
  11. // Gson 
  12. JsonObject jsonObjectGsonEmpty = gson.fromJson(jsonObjectEmptyCase, JsonObject.class); 
  13. System.out.println(jsonObjectGsonEmpty); 
  14. System.out.println(jsonObjectGsonEmpty.size()); 
  15. // 輸出: 
  16. // {} 
  17. // 0 

沒(méi)有異常,開(kāi)心。

看看空數(shù)組呢,畢竟[]感覺(jué)比{}更加容易出錯(cuò)。

  1. String jsonArrayEmptyCase = "[]"
  2.  
  3. // fastjson 
  4. JSONArray jsonArrayEmpty = JSON.parseArray(jsonArrayEmptyCase); 
  5. System.out.println(jsonArrayEmpty); 
  6. System.out.println(jsonArrayEmpty.size()); 
  7. // 輸出: 
  8. // [] 
  9. // 0 
  10.  
  11. // Gson 
  12. JsonArray jsonArrayGsonEmpty = gson.fromJson(jsonArrayEmptyCase, JsonArray.class); 
  13. System.out.println(jsonArrayGsonEmpty); 
  14. System.out.println(jsonArrayGsonEmpty.size()); 
  15. // 輸出: 
  16. // [] 
  17. // 0 

兩個(gè)框架也都沒(méi)有問(wèn)題,完美解析。

范型處理

解析泛型是一個(gè)非常常用的功能,我們項(xiàng)目中大部分fastjson代碼就是在解析json和Java Bean。

 

  1. // 實(shí)體類 
  2. User user = new User(); 
  3. user.setId(1L); 
  4. user.setUserName("馬云"); 
  5.  
  6. // fastjson 
  7. List<User> userListResultFastjson = JSONArray.parseArray(JSON.toJSONString(userList), User.class); 
  8. List<User> userListResultFastjson2 = JSON.parseObject(JSON.toJSONString(userList), new TypeReference<List<User>>(){}); 
  9. System.out.println(userListResultFastjson); 
  10. System.out.println("userListResultFastjson2" + userListResultFastjson2); 
  11. // 輸出: 
  12. // userListResultFastjson[User [Hash = 483422889, id=1, userName=馬云], null
  13. // userListResultFastjson2[User [Hash = 488970385, id=1, userName=馬云], null
  14.  
  15. // Gson 
  16. List<User> userListResultTrue = gson.fromJson(gson.toJson(userList), new TypeToken<List<User>>(){}.getType()); 
  17. System.out.println("userListResultGson" + userListResultGson); 
  18. // 輸出: 
  19. // userListResultGson[User [Hash = 1435804085, id=1, userName=馬云], null

可以看出,Gson也能支持泛型。

List/Map寫入

這一點(diǎn)fastjson和Gson有區(qū)別,Gson不支持直接將List寫入value,而fastjson支持。

所以Gson只能將List解析后,寫入value中,詳見(jiàn)如下代碼:

 

  1. // 實(shí)體類 
  2. User user = new User(); 
  3. user.setId(1L); 
  4. user.setUserName("馬云"); 
  5.  
  6. // fastjson 
  7. JSONObject jsonObject1 = new JSONObject(); 
  8. jsonObject1.put("user"user); 
  9. jsonObject1.put("userList", userList); 
  10. System.out.println(jsonObject1); 
  11. // 輸出: 
  12. // {"userList":[{"id":1,"userName":"馬云"},null],"user":{"id":1,"userName":"馬云"}} 
  13.  
  14. // Gson 
  15. JsonObject jsonObject = new JsonObject(); 
  16. jsonObject.add("user", gson.toJsonTree(user)); 
  17. System.out.println(jsonObject); 
  18. // 輸出: 
  19. // {"user":{"id":1,"userName":"馬云"},"userList":[{"id":1,"userName":"馬云"},null]} 

如此一來(lái),Gson看起來(lái)就沒(méi)有fastjson方便,因?yàn)榉湃隠ist是以gson.toJsonTree(user)的形式放入的。這樣就不能先入對(duì)象,在后面修改該對(duì)象了。(有些同學(xué)比較習(xí)慣先放入對(duì)象,再修改對(duì)象,這樣的代碼就得改動(dòng))

駝峰與下劃線轉(zhuǎn)換

駝峰轉(zhuǎn)換下劃線依靠的是修改Gson的序列化模式,修改為L(zhǎng)OWER_CASE_WITH_UNDERSCORES

 

  1. GsonBuilder gsonBuilder = new GsonBuilder(); 
  2. gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES); 
  3. Gson gsonUnderScore = gsonBuilder.create(); 
  4. System.out.println(gsonUnderScore.toJson(user)); 
  5. // 輸出: 
  6. // {"id":1,"user_name":"馬云"

常見(jiàn)問(wèn)題排雷

下面整理了我們?cè)诠卷?xiàng)目遷移Gson過(guò)程中,踩過(guò)的坑,這些坑現(xiàn)在寫起來(lái)感覺(jué)沒(méi)什么技術(shù)含量。但是這才是我寫這篇文章的初衷,幫助大家把這些很難發(fā)現(xiàn)的坑避開(kāi)。

這些問(wèn)題有的是在測(cè)試進(jìn)行回歸測(cè)試的時(shí)候發(fā)現(xiàn)的,有的是在自測(cè)的時(shí)候發(fā)現(xiàn)的,有的是在上線后發(fā)現(xiàn)的,比如Swagger掛了這種不會(huì)去測(cè)到的問(wèn)題。

Date序列化方式不同

不知道大家想過(guò)一個(gè)問(wèn)題沒(méi)有,如果你的項(xiàng)目里有緩存系統(tǒng),使用fastjson寫入的緩存,在你切換Gson后,需要用Gson解析出來(lái)。所以就一定要保證兩個(gè)框架解析邏輯是相同的,但是,顯然這個(gè)愿望是美好的。

在測(cè)試過(guò)程中,發(fā)現(xiàn)了Date類型,在兩個(gè)框架里解析是不同的方式。

  • fastjson:Date直接解析為Unix
  • Gson:直接序列化為標(biāo)準(zhǔn)格式Date

 

別了,阿里巴巴fastjson!企業(yè)項(xiàng)目遷移Gson全攻略

導(dǎo)致了Gson在反序列化這個(gè)json的時(shí)候,直接報(bào)錯(cuò),無(wú)法轉(zhuǎn)換為Date。

解決方案:

新建一個(gè)專門用于解析Date類型的類:

 

  1. import com.google.gson.TypeAdapter; 
  2. import com.google.gson.stream.JsonReader; 
  3. import com.google.gson.stream.JsonWriter; 
  4.  
  5. import java.io.IOException; 
  6. import java.util.Date
  7.  
  8. public class MyDateTypeAdapter extends TypeAdapter<Date> { 
  9.     @Override 
  10.     public void write(JsonWriter outDate value) throws IOException { 
  11.         if (value == null) { 
  12.             out.nullValue(); 
  13.         } else { 
  14.             out.value(value.getTime()); 
  15.         } 
  16.     } 
  17.  
  18.     @Override 
  19.     public Date read(JsonReader in) throws IOException { 
  20.         if (in != null) { 
  21.             return new Date(in.nextLong()); 
  22.         } else { 
  23.             return null
  24.         } 
  25.     } 

接著,在創(chuàng)建Gson時(shí),把他放入作為Date的專用處理類:

  1. Gson gson = new GsonBuilder().registerTypeAdapter(Date.class,new MyDateTypeAdapter()).create(); 

這樣就可以讓Gson將Date處理為Unix。

當(dāng)然,這只是為了兼容老的緩存,如果你覺(jué)得你的倉(cāng)庫(kù)沒(méi)有這方面的顧慮,可以忽略這個(gè)問(wèn)題。

SpringBoot異常

切換到Gson后,使用SpringBoot搭建的Web項(xiàng)目的接口直接請(qǐng)求不了了。報(bào)錯(cuò)類似:

  1. org.springframework.http.converter.HttpMessageNotWritableException 

因?yàn)镾pringBoot默認(rèn)的Mapper是Jackson解析,我們切換為了Gson作為返回對(duì)象后,Jackson解析不了了。

解決方案:

application.properties里面添加:

 

  1. #Preferred JSON mapper to use for HTTP message conversion 
  2. spring.mvc.converters.preferred-json-mapper=gson 

Swagger異常

這個(gè)問(wèn)題和上面的SpringBoot異常類似,是因?yàn)樵赟pringBoot中引入了Gson,導(dǎo)致 swagger 無(wú)法解析 json。

 

別了,阿里巴巴fastjson!企業(yè)項(xiàng)目遷移Gson全攻略

采用類似下文的解決方案(添加Gson適配器):

  • http://yuyublog.top/2018/09/03/springboot%E5%BC%95%E5%85%A5swagger/

GsonSwaggerConfig.java

 

  1. @Configuration 
  2. public class GsonSwaggerConfig { 
  3.     //設(shè)置swagger支持gson 
  4.     @Bean 
  5.     public IGsonHttpMessageConverter IGsonHttpMessageConverter() { 
  6.         return new IGsonHttpMessageConverter(); 
  7.     } 

IGsonHttpMessageConverter.java

 

  1. public class IGsonHttpMessageConverter extends GsonHttpMessageConverter { 
  2.     public IGsonHttpMessageConverter() { 
  3.         //自定義Gson適配器 
  4.         super.setGson(new GsonBuilder() 
  5.                 .registerTypeAdapter(Json.class, new SpringfoxJsonToGsonAdapter()) 
  6.                 .serializeNulls()//空值也參與序列化 
  7.                 .create()); 
  8.     } 

SpringfoxJsonToGsonAdapter.java

 

  1. public class SpringfoxJsonToGsonAdapter implements JsonSerializer<Json> { 
  2.     @Override 
  3.     public JsonElement serialize(Json json, Type type, JsonSerializationContext jsonSerializationContext) { 
  4.         return new JsonParser().parse(json.value()); 
  5.     } 

@Mapping JsonObject作為入?yún)惓?/h3>

有時(shí)候,我們會(huì)在入?yún)⑹褂妙愃疲?/p>

  1. public ResponseResult submitAudit(@RequestBody JsonObject jsonObject) {} 

如果使用這種代碼,其實(shí)就是使用Gson來(lái)解析json字符串。但是這種寫法的風(fēng)險(xiǎn)是很高的,平常請(qǐng)大家盡量避免使用JsonObject直接接受參數(shù)。

在Gson中,JsonObject若是有數(shù)字字段,會(huì)統(tǒng)一序列化為double,也就是會(huì)把count = 0這種序列化成count = 0.0。

為何會(huì)有這種情況?簡(jiǎn)單的來(lái)說(shuō)就是Gson在將json解析為Object類型時(shí),會(huì)默認(rèn)將數(shù)字類型使用double轉(zhuǎn)換。

  • 如果Json對(duì)應(yīng)的是Object類型,最終會(huì)解析為Map類型;其中Object類型跟Json中具體的值有關(guān),比如雙引號(hào)的""值翻譯為STRING。我們可以看下數(shù)值類型(NUMBER)全部轉(zhuǎn)換為了Double類型,所以就有了我們之前的問(wèn)題,整型數(shù)據(jù)被翻譯為了Double類型,比如30變?yōu)榱?0.0。

可以看下Gson的ObjectTypeAdaptor類,它繼承了Gson的TypeAdaptor抽象類:

 

別了,阿里巴巴fastjson!企業(yè)項(xiàng)目遷移Gson全攻略

解決方案:

  • 第一個(gè)方案:把入?yún)⒂脤?shí)體類接收,不要使用JsonObject
  • 第二個(gè)方案:與上面的解決Date類型問(wèn)題類似,自己定義一個(gè)Adaptor,來(lái)接受數(shù)字,并且處理。這種想法我覺(jué)得可行但是難度較大,可能會(huì)影響到別的類型的解析,需要在設(shè)計(jì)適配器的時(shí)候格外注意。

總結(jié)

這篇文章主要是為了那些需要將項(xiàng)目遷移到Gson框架的同學(xué)們準(zhǔn)備的。

一般來(lái)說(shuō),個(gè)人小項(xiàng)目,是不需要費(fèi)這么大精力去做遷移,所以這篇文章可能目標(biāo)人群比較狹窄。

但文章中也提到了不少通用問(wèn)題的解決思路,比如怎么評(píng)估遷移框架的必要性。其中需要考慮到框架兼容性,兩者性能差異,遷移耗費(fèi)的工時(shí)等很多問(wèn)題。

希望文章對(duì)你有所幫助。

責(zé)任編輯:未麗燕 來(lái)源: 今日頭條
相關(guān)推薦

2016-11-08 16:16:25

數(shù)據(jù)收集框架日志日志收集

2010-11-18 23:24:42

云遷移

2023-12-18 09:32:08

ES集群遷移上云oss插件

2013-06-08 11:13:00

Android開(kāi)發(fā)XML解析

2013-04-15 10:48:16

Xcode ARC詳解iOS ARC使用

2024-05-07 09:01:21

Queue 模塊Python線程安全隊(duì)列

2021-01-13 09:34:45

項(xiàng)目Gson框架

2010-04-23 14:04:23

Oracle日期操作

2010-06-28 10:43:47

2024-09-09 16:29:29

2018-12-14 11:00:18

2014-03-19 17:22:33

2009-12-14 14:32:38

動(dòng)態(tài)路由配置

2009-10-19 15:20:01

家庭綜合布線

2011-01-11 14:30:29

企業(yè)內(nèi)網(wǎng)開(kāi)發(fā)環(huán)境

2009-02-20 11:43:22

UNIXfish全攻略

2013-08-22 09:41:52

阿里巴巴去IOE王堅(jiān)

2012-02-15 13:30:48

Linux系統(tǒng)安全企業(yè)安全

2009-12-17 16:15:00

CCNA640-810

2010-08-25 14:36:02

DHCP服務(wù)器
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)