一、常用json解析庫比較及選擇
1.簡介
fastjson和gson是目前比較常用的json解析庫,並且現在我們項目代碼中,也在使用這兩個解析庫。
fastjson 是由阿里開發的,號稱是處理json效率最高的框架。而gson 是由google開發的,是功能比較全面的json解析工具。
2.比較
下面根據體積、性能、調用方式、文檔完備程度等幾個方面,來比較一下這兩個庫。
2.1 包體積
都使用當前最新版本的jar包,fastjson-1.1.56.android.jar 為209.7kb,gson-2.8.0.jar 為232kb。
兩者體積相差不大,都很小。
2.2 性能
因為fastjson號稱是效率最高的框架,這部分網上有很多人討論,看了一些關於性能比較的帖子
自己也寫了簡單的程序,使用最新版本的兩個庫測試。
測試方法為定義一個簡單的類 Example,並生成List<Example> 實例,分別使用兩個類庫執行 object => string 和 string => object 操作 10 次,計算消耗時間(毫秒)。
100 | 641 | 551 | 1.16 |
200 | 1191 | 970 | 1.23 |
300 | 1786 | 1445 | 1.235 |
400 | 2393 | 1911 | 1.25 |
500 | 3038 | 2550 | 1.19 |
1000 | 6054 | 5062 | 1.195 |
2000 | 12647 | 11044 | 1.145 |
3000 | 22488 | 17923 | 1.25 |
4000 | 30385 | 24178 | 1.26 |
考慮到移動端的實際使用場景,沒有繼續再測試更大數據量的耗時,上述時間也與設備性能和數據結構的復雜性有關。根據上述數據來看,確實fastjson比gson快了20%左右。
2.3 調用方式
只比較最簡單的由object=>string 和 string=>object 的操作,兩者都非常簡便
2.4 文檔完備程度
相對來說,fastjson的文檔很少,從github上,能找到一篇 簡單的示例代碼 和一篇 常見問題解答 。沒有比較全面的使用指南。
而gson的文檔就豐富的多了,包括 api , 使用指南 , 以及第三方寫的使用指南的鏈接 Gson Tutorial , Gson Tutorial Series 等。
2.5 流行程度
gson遠比fastjson流行,使用的人群更多。無論是在google上搜索fastjson/gson關鍵詞,還是在stackoverflow上搜索兩者相關的提問,兩者都存在數量級上的差距。
3.結論
通過兩者比較,雖然在性能上fastjson比gson更優,但在我們具體的業務場景下,一般只會涉及到小數據量的解析操作,gson並不會比fastjson額外耗費太多的解析時間。
另外,從文檔完備程度和解析庫的流行程度來說,gson文檔相對更完善,對開發人員比較友好。另外更廣泛的使用人群,也方便開發人員更容易解決或規避使用中會出現的問題。
再有,個人感覺fastjson的一些特性相對gson來說,並不是太好,比如 對所有的getter方法對應的屬性,都做處理 , 忽略大小寫 。 以及在編寫demo時感覺,fastjson相對gson來說,對代碼有更多要求,相對來說感覺gson更傻瓜一些。
二、相關文檔及使用方式
當前使用gson的最新版源碼,版本為2.8.0,根據 CHANGELOG 中描述,在2.5版本時,將最小支持JDK版本升為 1.6。
代碼路徑:http://athena.devops.letv.com/#/admin/projects/ui/apps/LeGson
jar包:LeGson-v1.0.0.jar
gson github:https://github.com/google/gson
增加了 LeGson 類,對 gson 做了簡單的封裝
- 使用單例的方式保存了一個 gson 對象,省去了調用方創建 gson 對象的操作。
- catch 住調用 gson 時可能產生的json解析異常,以 warn log 的形式打印出來, TAG 為 LeGson,並返回 null
目前 LeGson 封裝了下面方法,后續如果有需要會繼續添加。
toJson
封裝 gson 方法
public
String toJson(Object src)
|
調用示例
String str = LeGson.toJson(user);
|
fromJson
封裝 gson 方法
public
<T> T fromJson(String json, Type typeOfT)
|
調用示例
String jsonArray =
"[\"test1\",\"test2\",\"test3\"]"
;
List<String> stringList = LeGson.fromJson(jsonArray,
new
TypeToken<List<String>>() {}.getType());
|
封裝 gson 方法
public
<T> T fromJson(String json, Class<T> classOfT)
|
調用示例
User user = LeGson.fromJson(str, User.
class
);
|
我們會將編好的gson jar包放在項目 /vendor/letv/frameworks/base/3rd_jars 目錄下,可通過如下方式引用
在Android.mk文件中添加
LOCAL_JAVA_LIBRARIES := gsonjar
|
在AndroidManifest.xml文件中添加
AndroidManifest.xml
<
application
android:name
=
"xxx"
android:icon
=
"@drawable/ic_app"
android:label
=
"@string/app_name"
android:theme
=
"@style/Feedback.Theme.Holo.Letv"
>
<
uses-library
android:name
=
"gsonjar"
/>
<
activity
android:name
=
".Activity"
android:theme
=
"@style/Feedback.Theme.Holo.Letv"
/>
|
三、調用示例
1. 基本用法
gson提供了 fromJson() 和 toJson() 兩個直接用於解析和生成的方法,前者實現反序列化,后者實現了序列化。
基本數據類型
Gson gson =
new
Gson();
String jsonNumber = gson.toJson(
100
);
// 100
String jsonBoolean = gson.toJson(
false
);
// false
String jsonString = gson.toJson(
"String"
);
// "String"
|
POJO類的生成與解析
public
class
User {
public
int
id;
public
String name;
}
|
生成Json:
Gson gson =
new
Gson();
User user =
new
User(
123
,
"test-name"
);
String jsonStr = gson.toJson(user);
|
解析Json:
Gson gson =
new
Gson();
String str =
"{\"name\":\"test_name\", \"id\":234}"
;
User user = gson.fromJson(str, User.
class
);
|
2.屬性重命名 @SerializedName 注解的使用
當期望的json格式為
{
"name"
:
"test_name"
,
"id"
:234}
|
而實際的格式為
{
"user_name"
:
"test_name"
,
"user_id"
:234}
|
可對 User 類中相關屬性添加@serializedName注解
public
class
User {
@SerializedName
(
"user_id"
)
public
int
id;
@SerializedName
(
"user_name"
)
public
String name;
}
|
這樣的話,可以在保留前后端命名習慣的前提下完成數據解析。
如果要兼容多種不同的命名方式,比如:
{
"user_name"
:
"test_name"
,
"user_id"
:234}
{
"custom_name"
:
"test_name"
,
"custom_id"
:234}
{
"student_name"
:
"test_name"
,
"student_id"
:234}
|
可使用@SerializedName注解的 alternate 屬性,傳入數組參數
@SerializedName
(value =
"user_id"
, alternate = {
"student_id"
,
"custom_id"
})
public
int
id;
|
當指定的三個屬性中任意一個出現時,都可以得到正確的結果。
當多種情況同時出現時,保留最后一個出現的值
String str =
"{\"student_name\":\"test_name\", \"custom_id\":234, \"user_name\":\"user-name\"}"
;
User tmp = gson.fromJson(str, User.
class
);
// name = "user-name"
|
3.解析成數組或列表
String str =
"[\"test-1\",\"test-2\",\"test-3\",\"test-4\",\"test-5\"]"
;
String[] strs = gson.fromJson(str, String[].
class
);
List<String> strList = gson.fromJson(str,
new
TypeToken<List<String>>() {}.getType());
|
或使用上面定義的User類型為例:
List<User> userList = gson.fromJson(jsonstr,
new
TypeToken<List<User>>() {}.getType());
|
4. 更多詳細功能介紹
上面只是列出了gson比較基本的功能,其實gson對於json的解析處理是非常的靈活的,大家可查看更多gson的使用方式,來適應實際工作中的各種解析場景。
下面列出一些介紹的文章: