一、前言
Json已成為計算機編程中最常用的數據傳輸和存儲格式之一,所以對Json的序列化和反序列化工具的選擇也是互聯網系統中比較重要的環節,尤其在高並發下的執行效率,可能會直接影響系統的吞吐率。本文將從功能和性能兩方面對常用的四種Json處理工具進行對比,以便選出符合我們系統需要的Json處理工具。
二、功能對比
項目 |
json-lib |
fastJson |
Jackson |
Gson |
最新版本號 |
2.4 |
1.2.51 |
2.97 |
2.8.5 |
最后更新 |
2010/12/14 |
2018/9/30 |
2018/9/19 |
2018/5/22 |
被引用次數 |
426 |
1492 |
5185 |
8655 |
是否支持注解 |
No |
Yes |
Yes |
Yes |
Map中的key為Long時 |
報錯 |
正常輸出,不是標准格式 |
會把key轉成String |
會把key轉成String |
特殊字符 |
支持 |
支持 |
支持 |
支持 |
控制字符 |
支持 |
支持 |
支持 |
支持 |
表情字符 |
支持 |
支持 |
支持 |
支持 |
從上表可以得出以下結論:
- Sf的json-lib已經很久沒有更新了,其它三種都還一直在更新維護
- 從Maven庫中被引用的次數來看,sf的json-lib也是使用的最少的,而Gson和Jackson被使用的較多
- 當對象中包含key為Long類型的Map時,json-lib序列化時會報錯,fastJson是正常以整數作為key輸出,Jackson和Gson會把key轉換成字符串輸出。fastJson的處理方式會導致反序列化報錯
- 經測試,四個工具包對特殊字符的處理都沒有問題
其它說明:
1、 Jackson、json-lib反序列化時,要求所有涉及的Bean必須存在默認的構造函數
2、 fastJson、json-lib反序列化,再序列化之后得到的JSON與之前可能不一致,因為Map的順序會變,而Jackson、gson反序列化之后是一致的,其使用了LinkedHashMap保證順序
3、 fastJson、Gson輸出json時會忽略值為null的字段;對於值為null的字段,jackson輸出null,而json-lib輸出空字符串
4、 fastJson反序列化時,二級對象中的List出現過沒有被反序列化的情況,但后來測試又可以反序列化了,目前還沒有找到規律
三、性能對比
1) 序列化操作
第一組:
測試環境:本地Windows、2核8G內存,64位OS
Bean對象:小對象,輸出Json后約1.83KB
結論:
- 對於小對象的序列化,json-lib在高並發的情況下效率明顯不如其它三個工具,同時json-lib的CPU占用率達到100%
- fastJson、Jackson和Gson對小對象的序列化執行效率差異不明顯,但Jackson更優
第二組:
測試環境:本地Windows、2核8G內存,64位OS
Bean對象:大對象,輸出Json后約8.99KB
結論:
- 對於大對象,sf的json-lib執行效率明顯不如其它三個工具。在高並發的情況下,Jackson的執行效率幾乎是json-lib的10倍;
- Gson的執行效率也明顯不如fastJson和Jackson,消耗時間幾乎是它們的2倍;
- 執行效率上,Jackson優於fastJson
- Gson對CPU的占用率控制的最好,一直在80%左右
第三組:
測試環境:本地Windows、2核8G內存,64位OS
Bean對象:特大對象,輸出Json后約56.1KB。因在小對象測試中證明json-lib和gson在高並發下效率不好,所以大對象測試中忽略這兩個包,只對比fastjson和jackson。
結論:
- 執行效率上,Jackson優於fastJson。網上很多朋友都說fastjson比jackson快,可能是使用了jackson1.x的緣故,后面有時間再測試一下。
2) 反序列化操作
第一組:
測試環境:本地Windows、2核8G內存,64位OS
輸入數據:小對象,輸入Json約1.83KB
總結:
- 對於小文件的反序列化,json-lib效率明顯不行
- 在高並發的情況下,Jackson的效率最優
- 對於小文件的反序列化操作,即使高並發的情況下,CPU占用率也表現比較平穩,相對來說fastJson的CPU占用率更高
第二組:
測試環境:本地Windows、2核8G內存,64位OS
輸入數據:大對象,輸入Json約9.83KB
結論:
- 對於大文件的反序列化,json-lib和Gson的執行效率明顯不如fastJson和Jackson
- 高並發的情況下,Jackson的執行效率優於fastJson
第三組:
測試環境:本地Windows、2核8G內存,64位OS
輸入數據:特大對象,輸入Json約56.1KB
結論:
- 對於更大文件的反序列化,json-lib和Gson的執行效率明顯不如fastJson和Jackson
- Jackson的執行效率優於fastJson,尤其是高並發的情況下
四、總結
經過以上測試及對比,基本可以得出結論:Jackson工具包(測試中使用2.9.5版本)在功能和性能方面都表現的更出色,在新開發系統時可以考慮使用Jackson進行JSON數據的處理。理由如下:
- Jackson使用廣泛,並且仍然在持續更新
- Jackson對特殊字符支持完好
- 在序列化和反序列化時,Jackson的性能在測試的4個工具包中表現最優,尤其是對大文件或高並發時表現更好。
五、使用Jackson的注意事項
在使用Jackson時,有一些注意事項,需要在編寫代碼時注意,具體如下:
1) 反序列化時,要求所有涉及的Bean必須存在默認的構造函數,否則會報錯;
2) 反序列化時,如果json中有部分字段是對象中不存在的屬性,或對象中無get/set方法,會報“UnrecognizedPropertyException”,解決方法是:
在類中添加 @JsonIgnoreProperties(ignoreUnknown = true),
或者代碼中設置:
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
3) 反序列化的類是抽象類或者接口,就會導致“Can not construct instance of”這個異常。
解決方法:添加@JsonDeserialize(as = Cat.class)注解
如下:
Json文件:
{"id":1001,"name":"布萊德","weight":1.67,"animal":{"color":"Blue"}}
4) 當反序列化的JSON中包含了單引號而不是雙引號的時候,會拋“Unexpected character (''' (code 39))”異常,
如Json:{"id":1001,"name":'布萊德','weight':1.67, "feild1": 56}
解決方法:
JsonFactory factory = new JsonFactory();
factory.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
ObjectMapper mapper = new ObjectMapper(factory);
六、Jackson從1.x遷移到2.x的步驟
1) 修改POM文件
舊依賴 |
新依賴 |
<dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>1.x.x</version> </dependency> |
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.9.5</version> </dependency> |
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>1.x.x</version> </dependency> |
<dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.9.5</version> </dependency> |
2) 包名更改
所有以org.codehaus.jackson開頭的包名都替換成com.fasterxml.jackson開頭的。
3) 設置屬性的代碼調整
SerializationConfig.Feature.* 改成 SerializationFeature.*
DeserializationConfig.Feature.* 改成 DeserializationFeature.*