1. 程式人生 > >Gson與FastJson比較

Gson與FastJson比較

rom 選型 map bean google clas ... arr 功能

一. 簡介和優劣

1.Google的Gson

Gson是目前功能最全的Json解析神器,Gson當初是為因應Google公司內部需求而由Google自行研發而來,但自從在2008年五月公開發布第一版後已被許多公司或用戶應用。Gson的應用主要為toJson與fromJson兩個轉換函數,無依賴,不需要例外額外的jar,能夠直接跑在JDK上。
而在使用這種對象轉換之前需先創建好對象的類型以及其成員才能成功的將JSON字符串成功轉換成相對應的對象。

類裏面只要有get和set方法,Gson完全可以將復雜類型的json到bean或bean到json的轉換,是JSON解析的神器。

Gson在功能上面無可挑剔,但是性能上面比FastJson有所差距。

2.阿裏巴巴的FastJson

Fastjson是一個Java語言編寫的高性能的JSON處理器,由阿裏巴巴公司開發。
無依賴,不需要例外額外的jar,能夠直接跑在JDK上。 FastJson在復雜類型的Bean轉換Json上會出現一些問題,可能會出現引用的類型,導致Json轉換出錯,需要制定引用。

FastJson采用獨創的算法,將parse的速度提升到極致,超過所有json庫。

3. 其他

json-lib最開始的也是應用最廣泛的json解析工具,json-lib 不好的地方確實是依賴於很多第三方包,對於復雜類型的轉換,json-lib對於json轉換成bean還有缺陷,比如一個類裏面會出現另一個類的list或者map集合,json-lib從json到bean的轉換就會出現問題。json-lib在功能和性能上面都不能滿足現在互聯網化的需求。
相比json-lib框架,Jackson所依賴的jar包較少,簡單易用並且性能也要相對高些。
而且Jackson社區相對比較活躍,更新速度也比較快。
Jackson對於復雜類型的json轉換bean會出現問題,一些集合Map,List的轉換出現問題。
Jackson對於復雜類型的bean轉換Json,轉換的json格式不是標準的Json格式

綜上,在項目選型的時候可以使用Google的Gson和阿裏巴巴的FastJson兩種並行使用,
如果只是功能要求,沒有性能要求,可以使用google的Gson,
如果有性能上面的要求可以使用Gson將bean轉換json確保數據的正確,使用FastJson將Json轉換Bean。

二、基本使用方式

Gson

//解成對象
Fromat mFromat = new Gson().fromJson(jsonStringObject, Fromat.class);

//解成對象組
LinkedList<Fromat> list = new LinkedList<MainActivity.Fromat
>(); Type type = new TypeToken<LinkedList<Fromat>>(){}.getType(); list = new Gson().fromJson(jsonStringArray, type); //泛型統一封裝時 需要傳個 type 進來 new TypeToken<LinkedList<Fromat>>(){}.getType(); fromJson(String json, Type typeOfT) public <T> T fromJson(String json, Type typeOfT)

fastJson

//解析成對象
Fromat fastjsonObject = JSON.parseObject(jsonObjectString, Fromat.class);

//解析成對象組
List<Fromat> fastjsonArray = JSON.parseArray(jsonArrayString, Fromat.class);

//泛型統一封裝時 需要傳個 type 進來 或者TypeReference 也可以也是調用的type
new TypeReference<Fromat>() {}
new TypeReference<Fromat>() {}.getType()
public static <T> T parseObject(String input, Type clazz, Feature... features)
public static <T> T parseObject(String text, TypeReference<T> type, Feature... features)

三、細節比較

1、屬性和set方法名稱不一致時

現在我有這麽一個Bean,屬性名為firstName,但是它的set方法卻是setName(),而不是setFirstName()
下面我使用Gson與FastJson分別將這樣的一個Bean轉成一個Json字符串,大家猜會有什麽區別?

    @Test
    public void toJson() {
        Bean bean = new Bean();
        bean.setAge(24);
        bean.setName("紮巴也"); //方法是setName,屬性是firstName

        String fastJson = JSON.toJSONString(bean);
        System.out.println("fastJson=" + fastJson);

        String gson = new Gson().toJson(bean);
        System.out.println("gson=" + gson);
    }

輸出結果:

fastJson={"age":24,"name":"紮巴也"}
gson={"firstName":"紮巴也","age":24}

序列化時fastJson是按照set方法的名字來轉換的,而gson則是按照屬性的名字來轉換的。

不信?好,我們再來看看反序列化時會怎樣?

@Test
    public void fromJson() {
        String json = "{\"age\":24,\"name\":\"紮巴也\"}";

        Bean fastjson = JSON.parseObject(json, Bean.class);
        System.out.println("fastJson=" + fastjson.toString());

        Bean gson = new Gson().fromJson(json, Bean.class);
        System.out.println("gson=" + gson.toString());
    }

輸出結果:

fastJson=Bean{firstName=‘紮巴也‘, age=24}
gson=Bean{firstName=‘null‘, age=24}

因為Bean類裏面有name的set方法,所以fastJson解析時調用了setName,所以firstName有值
但是Bean類裏面卻沒有name屬性,所以gson解析時,firstName沒有值

2、有屬性,無set方法

現在我有這麽一個Person,屬性名為name,但是它沒有name的set方法
那麽,我來解析這樣一個字符串時,FastJson和Gson會有什麽區別呢?

{"age":24,"name":"紮巴也"}

測試代碼:

@Test
    public void fromJsonNoSet() {
        String json = "{\"age\":24,\"name\":\"紮巴也\"}";

        Person fastjson = JSON.parseObject(json, Person.class);
        System.out.println("fastJson=" + fastjson.toString());

        Person gson = new Gson().fromJson(json, Person.class);
        System.out.println("gson=" + gson.toString());
    }

輸出結果:

fastJson=Person{name=‘null‘, age=24}
gson=Person{name=‘紮巴也‘, age=24}

因為Person沒有name的set方法,所以fastJson解析的name為null

再次證明,fastJson是按照set方法的名字來轉換的,而gson則是按照屬性的名字來轉換的。

那麽,無屬性,有set方法時,兩者有什麽區別呢?(其實沒有屬性的話,set方法調用了沒啥作用)
測試代碼:

@Test
    public void fromJsonNoFiled() {
        String json = "{\"age\":24,\"name\":\"紮巴也\"}";

        Student fastjson = JSON.parseObject(json, Student.class);
        System.out.println("fastJson=" + fastjson.toString());

        Student gson = new Gson().fromJson(json, Student.class);
        System.out.println("gson=" + gson.toString());
    }

輸出結果:

調用了setName:紮巴也
fastJson=Student{age=24}
gson=Student{age=24}

fastJson調用了set方法,而gson沒有調用set方法。
同樣證明,fastJson是按照set方法的名字來轉換的,而gson則是按照屬性的名字來轉換的。

3、無默認的無參構造方法

現在有這麽一個Teacher類,他只有一個兩個參數的構造方法,沒有默認的無參構造方法,那麽,我來解析這樣一個字符串時,FastJson和Gson會有什麽區別呢?

{"age":24,"name":"紮巴也"}

測試代碼:

    @Test
    public void fromJsonNoDefaultConstructor() {
        String json = "{\"age\":24,\"name\":\"紮巴也\"}";

        Teacher gson = new Gson().fromJson(json, Teacher.class);
        System.out.println("gson=" + gson.toString());

        Teacher fastjson = JSON.parseObject(json, Teacher.class);
        System.out.println("fastJson=" + fastjson.toString());
    }

這裏,Gson可以正常的解析,但是,fastJson則會報錯,因為沒有默認的無參構造方法。
這說明了反序列化時,fastJson是通過無參構造方法來創建對象的,那麽gson又是怎麽創建對象的呢?(是調用了Unsafe.allocateInstance()這個native方法來創建對象的。
但是,我們知道,這個方法直接操作內存,是不安全的,那麽,如果反序列化的那個類,存在默認的無參構造方法呢?)

4、有默認的無參構造方法

    @Test
    public void fromJsonHasDefaultConstructor() {
        String json = "{\"age\":24,\"name\":\"紮巴也\"}";

        Boss gson = new Gson().fromJson(json, Boss.class);
        System.out.println("gson=" + gson.toString());

        Boss fastjson = JSON.parseObject(json, Boss.class);
        System.out.println("fastJson=" + fastjson.toString());
    }

gson和fastJson都調用了默認的無參構造方法.
至此,我們可以得出結論:
有默認的無參構造方法時,gson和fastJson都會調用它來創建對象,沒有默認的無參構造方法時,fastJson會直接報錯!而gson則會調用Unsafe.allocateInstance()這個native方法直接在內存上創建對象。

四、Gson中使用泛型

例:JSON字符串數組
當我們要通過Gson解析這個json時,一般有兩種方式:使用數組,使用List。而List對於增刪都是比較方便的,所以實際使用是還是List比較多。

數組比較簡單

Gson gson = new Gson();
String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";
String[] strings = gson.fromJson(jsonArray, String[].class);

但對於List將上面的代碼中的 String[].class 直接改為 List

為了解決的上面的問題,Gson為我們提供了TypeToken來實現對泛型的支持,所以當我們希望使用將以上的數據解析為List

Gson gson = new Gson();
String jsonArray = "[\"Android\",\"Java\",\"PHP\"]";
String[] strings = gson.fromJson(jsonArray, String[].class);
List<String> stringList = gson.fromJson(jsonArray, new TypeToken<List<String>>() {}.getType());

註:TypeToken的構造方法是protected修飾的,所以上面才會寫成new TypeToken

參考:
https://www.jianshu.com/p/e740196225a4
https://blog.csdn.net/lckj686/article/details/51587073
https://blog.csdn.net/xiaoke815/article/details/52920405
https://www.jianshu.com/p/153111dde324

Gson與FastJson比較