1. 程式人生 > >JSON轉換器,強烈推薦GSON,以及一些踩的坑

JSON轉換器,強烈推薦GSON,以及一些踩的坑

前言: 現在很流行前後分離,而我這裡是完全的前後分離,後端只需要提供json資料給別人就行,無論是你的前端是開發c/s的還是app的.那麼就經常會用到json轉換器了,當然也可以憑藉自己的能力直接去寫一個.

  • 目前我所知的四種json轉換器:

1.json-lib

json-lib最開始的也是應用最廣泛的json解析工具,json-lib 不好的地方確實是依賴於很多第三方包,
包括commons-beanutils.jar,commons-collections-3.2.jar,commons-lang-2.6.jar,commons-logging-1.1.1.jar,ezmorph-1.0.6.jar,

對於複雜型別的轉換,json-lib對於json轉換成bean還有缺陷,比如一個類裡面會出現另一個類的list或者map集合,json-lib從json到bean的轉換就會出現問題。
json-lib在功能和效能上面都不能滿足現在網際網路化的需求。
2.開源的Jackson
相比json-lib框架,Jackson所依賴的jar包較少,簡單易用並且效能也要相對高些。
而且Jackson社群相對比較活躍,更新速度也比較快。
Jackson對於複雜型別的json轉換bean會出現問題,一些集合Map,List的轉換出現問題。
Jackson對於複雜型別的bean轉換Json,轉換的json格式不是標準的Json格式

3.Google的Gson
Gson是目前功能最全的Json解析神器,Gson當初是為因應Google公司內部需求而由Google自行研發而來,
但自從在2008年五月公開發布第一版後已被許多公司或使用者應用。
Gson的應用主要為toJson與fromJson兩個轉換函式,無依賴,不需要例外額外的jar,能夠直接跑在JDK上。
而在使用這種物件轉換之前需先建立好物件的型別以及其成員才能成功的將JSON字串成功轉換成相對應的物件。
類裡面只要有get和set方法,Gson完全可以將複雜型別的json到bean或bean到json的轉換,是JSON解析的神器。
Gson在功能上面無可挑剔,但是效能上面比FastJson有所差距。

4.阿里巴巴的FastJson
Fastjson是一個Java語言編寫的高效能的JSON處理器,由阿里巴巴公司開發。
無依賴,不需要例外額外的jar,能夠直接跑在JDK上。
FastJson在複雜型別的Bean轉換Json上會出現一些問題,可能會出現引用的型別,導致Json轉換出錯,需要制定引用。
FastJson採用獨創的演算法,將parse的速度提升到極致,超過所有json庫。

綜上4種Json技術的比較,在專案選型的時候可以使用Google的Gson和阿里巴巴的FastJson兩種並行使用,
如果只是功能要求,沒有效能要求,可以使用google的Gson,

如果有效能上面的要求可以使用Gson將bean轉換json確保資料的正確,使用FastJson將Json轉換Bean

  • 基本使用就不說了,百度很多
  • 踩的坑

1.fastjson轉換帶泛型的類是可以的,但是需要帶泛型的類提供無參構造

//pageInfo是com.github.pagehelper.PageHelper分頁工具提供的類
PageInfo<xxx> pageInfo =  JSON.parseObject(json,new TypeReference<PageInfo<xxxx>>(){});

執行後會報出:


翻譯過來: 預設建構函式沒找到

解決方案: 使用Gson來解析

2.使用Gson來轉換帶泛型的類

//pageInfo是com.github.pagehelper.PageHelper分頁工具提供的類,
PageInfo<xxx>  pageInfo = new Gson().fromJson(cacheValue, new TypeToken<PageInfo<ExchangeEntity>>() {
            }.getType());

執行後報出:


一看就知道應該是日期轉換的問題

解決方案: 手動註冊一個介面卡,將日期型別設定為長整型

解決程式碼:

            GsonBuilder builder = new GsonBuilder();
            // Register an adapter to manage the date types as long values
            builder.registerTypeAdapter(Date.class, new JsonDeserializer<Date>() {
				@Override
				public Date deserialize(JsonElement json, java.lang.reflect.Type arg1, JsonDeserializationContext arg2)
						throws JsonParseException {
					 return new Date(json.getAsJsonPrimitive().getAsLong());
				}
            });
            Gson gson = builder.create();
            PageInfo<xxx> pageInfo = new Gson().fromJson(json, new TypeToken<PageInfo<xxx>>() {
            }.getType());

3.用gson轉換物件為json時出現缺失欄位和空屬性不轉換的問題,經查詢發現,Gson就是這種json轉換的情況,如何解決?

這樣可以實現序列化空值:

           GsonBuilder gsonBuilder = new GsonBuilder();  
           gsonBuilder.serializeNulls(); //這個才是祕密

           Gson gson = gsonBuilder.create();

4.今天程式中出現一個BUG,從快取中讀取字串轉List<物件>報錯,發現是將List<物件>轉JSON字串的時候,日期出現問題了,Gson在處理Date格式時有個小陷阱,在不同環境中部署時可能會遇到問題。 

Gson預設處理Date物件的序列化/反序列化是通過一個SimpleDateFormat物件來實現的,通過下面的程式碼去獲取例項: 

DateFormat.getDateTimeInstance()  
在不同的locale環境中,這樣獲取到的SimpleDateFormat的模式字串會不一樣。 

例如說,在我的開發機是Windows XP SP3,zh_CN.GBK,模式字串是: 

"yyyy-M-d H:mm:ss"  

而在我們的一臺測試伺服器上,RHEL 5.4,en_US.UTF-8,模式字串則是: 

"MMM d, yyyy h:mm:ss a"  

這就使得同樣的Date物件通過Gson來序列化為JSON後內容不同。例如說要序列化的日期是2010-08-19 16:13:57,那麼在我的開發機上得到的是: 

"2010-8-19 16:13:57"  

而在那臺測試伺服器上則是: 

"Aug 19, 2010 4:13:57 PM"  
這就……鬱悶了。在一邊序列化的內容在另一邊會反序列化失敗。 

解決方案:

1.為了避免使用Gson時遇到locale影響Date格式的問題,使用GsonBuilder來建立Gson物件,在建立過程中呼叫GsonBuilder.setDateFormat(String)指定一個固定的格式即可。例如: 

Gson gson = new GsonBuilder()  
  .setDateFormat("yyyy-MM-dd HH:mm:ss")  
  .create(); 

2.使用JSONObject.toJSONString()方式來轉為json字串,這個JSONObject是屬於fastJson中的一個類,它對於Date()型別是直接序列化為時間戳.這樣配合Gson反序列化,相得益彰!

以後碰到了json轉換相關的問題,會繼續補充本帖,也歡迎大家來討論,來指點我一下.