1. 程式人生 > >JSON解析類庫之Fastjson(1) --- Fastjson類庫學習, 生成與解析json資料,json字串與Java物件互轉

JSON解析類庫之Fastjson(1) --- Fastjson類庫學習, 生成與解析json資料,json字串與Java物件互轉

JSON解析類庫之Fastjson(1) --- Fastjson基礎知識、簡單JavaBean與複雜Bean物件與JSON互轉
-- Fastjson類庫學習, 生成與解析json資料,json字串與Java物件互轉
在日誌解析、前後端資料傳輸互動中,經常會遇到 String 與 map、json、xml 等格式相互轉換與解析的場景,其中 json 基本成為了跨語言、跨前後端的事實上的標準資料互動格式。應該來說各個語言中解析 json 的庫都一大片(具體 json 格式與三方庫的介紹請見: http://www.json.org/json-zh.html ),比如 python 都整合在了內建庫中,成為標準 API,今天我們要聊的是 java 中如何方便的使用 json 格式。
從上面的連結介紹中我們可以看到,java 的三方 json 庫是最多的,可謂百花齊放百家爭鳴的節奏。。。但是,某些庫存在鏈式依賴的問題,使用的時候要注意,如果你沒用 maven 管你你的依賴,用起來會很痛苦,比如 json-lib、smart-json 等。下面我要推薦的是阿里巴巴公司開源的一個 json 庫:Fastjson,這個庫在解析速度易用性上來說都很優秀。   1、Fastjson簡介: Fastjson是一個Java語言編寫的高效能功能完善的JSON庫(JSON處理器,解析類庫)。 1、遵循http://json.org標準,為其官方網站收錄的參考實現之一。 2、功能強大,支援JDK的各種型別,包括基本型別、JavaBean、Collection、Map、Date、Enum、泛型等。
3、無依賴,不需要例外額外的jar,能夠直接跑在JDK上。 4、開源,使用Apache License 2.0協議開源。 5、測試充分,fastjson有超過1500個testcase,每次構建都會跑一遍,豐富的測試場景保證了功能穩定。 Fastjson採用獨創的演算法,將parse的速度提升到極致,超過所有json庫,包括曾經號稱最快的jackson。並且還超越了google的二進位制協議protocol buf。Fastjson完全支援http://json.org的標準,也是官方網站收錄的參考實現之一。支援各種JDK型別。包括基本型別、JavaBean、Collection、Map、Enum、泛型等。支援JDK 5、JDK 6、Android、阿里雲手機等環境。
阿里巴巴FastJson是一個Json處理工具包,包括“序列化”和“反序列化”兩部分,它具備如下特徵: 速度最快,測試表明,fastjson具有極快的效能,超越任其他的Java Json parser。包括自稱最快的Jackson 功能強大,完全支援Java Bean、集合、Map、日期、Enum,支援範型,支援自省;無依賴,能夠直接執行在Java SE 5.0以上版本;支援Android;開源 (Apache 2.0) 如何獲得Fastjson? 你可以通過如下地方下載fastjson: maven中央倉庫: http://central.maven.org/maven2/com/alibaba/fastjson/ Sourceforge.net : https://sourceforge.net/projects/fastjson/files/ 在maven中如何配置fastjson依賴 : fastjson最新版本都會發布到maven中央倉庫,你可以直接依賴。 版本建議:建議使用1.2.28及其以後的版本,之前的1.2.24之前的版本說是有個小漏洞,之後的版本已經修復了。

2. fastjson主要的API哪些?

fastjson入口類是com.alibaba.fastjson.JSON,主要的APIJSON.toJSONString,和parseObject

packagecom.alibaba.fastjson;
publicabstractclassJSON{
      publicstaticfinalStringtoJSONString(Objectobject);
      publicstaticfinal<T>TparseObject(Stringtext, Class<T>clazz, Feature... features);
}

序列化:

基本序列化

序列化就是把JavaBean物件轉化成JSON格式的文字。

String jsonString =JSON.toJSONString(obj);

反序列化:

VO vo =JSON.parseObject("...", VO.class);

泛型反序列化:

importcom.alibaba.fastjson.TypeReference;

List<VO> list =JSON.parseObject("...", newTypeReference<List<VO>>() {});
fastjson的一些高階特性: 使用單引號: 標準的JSON是使用雙引號的,javascript支援使用單引號格式的json文字,fastjson也支援這個特性,開啟SerializerFeature.UseSingleQuotes這個特性就可以了了,例如: Object o = ...; String text = JSON.toJSONString(o, SerializerFeature.UseSingleQuotes); fastjson序列化時可以選擇的SerializerFeature有十幾個,你可以按照自己的需要去選擇使用。 日期格式化 fastjson直接支援日期型別資料的格式化,包括java.util.Date、java.sql.Date、java.sql.Timestamp、java.sql.Time。 預設情況下,fastjson將Date型別序列化為long這個使得序列化和反序列化的過程不會導致時區問題。如: 例如: long  millis = 1324138987429L; Date date = new  Date(millis);         System.out.println(JSON.toJSONString(date)); 輸出的結果是: 1324138987429 fastjson還提供了基於格式化輸出的SerializerFeature,例如: JSON.toJSONString(date, SerializerFeature.WriteDateUseDateFormat);
輸出的結果為:
"2011-12-18 00:23:07"
你可以指定輸出日期的格式,比如修改為輸出毫秒:
JSON.toJSONStringWithDateFormat(date, "yyyy-MM-dd HH:mm:ss.SSS");
輸出的結果為:
"2011-12-18 00:23:07.429"
使用WriteClassName特性 fastjson支援序列化時寫入型別資訊,從而使得反序列化時不至於型別資訊丟失。例如: Color color = Color.RED; String text = JSON.toJSONString(color, SerializerFeature.WriteClassName); System.out.println(text); 輸出結果: {"@type":"java.awt.Color","r":255,"g":0,"b":0,"alpha":255} 由於序列化帶了型別資訊,使得反序列化時能夠自動進行型別識別,例如: String text = ...; // {"@type":"java.awt.Color","r":255,"g":0,"b":0,"alpha":255} Color color = (Color) JSON.parse(text); 瀏覽器和裝置相容 fastjson預設的序列化內容,是對序列化結果緊湊做了優化配置,使得序列化之後長度更小,但是這種優化配置是對一些瀏覽器和裝置不相容的。比如說在iphone上相容emoji(繪文字)。 JSON.toJSONString(o, SerializerFeature.BrowserCompatible);
迴圈引用 很多場景中,我們需要序列化的物件中存在迴圈引用,在許多的json庫中,這會導致stackoverflow。在功能強大的fastjson中,你不需要擔心這個問題。例如: A a = new  A(); B b = new  B(a); a.setB(b); String text = JSON.toJSONString(a); // {"b":{"a":{"$ref":".."}}} A a1 = JSON.parseObject(text, A.class); Assert.assertTrue(a1 == a1.getB().getA());

引用是通過"$ref"來表示的

引用 描述
"$ref":".." 上一級
"$ref":"@" 當前物件,也就是自引用
"$ref":"$" 根物件
"$ref":"$.children.0" 基於路徑的引用,相當於 root.getChildren().get(0)

使用@JSONField Annotation註解

在某些場景,你可能需要定製序列化輸出,比如說,希望序列化之後採用"ID",而不是"id",你可以使用@JSONField這個Annotation。

public class User {

    @JSONField(name="ID")

    public int getId() { ... }

}

User user = ...;

JSON.toJSONString(user); // {"ID":234}

從json-lib中升級

如果你已經使用了json-lib,並且痛恨他蝸牛般的速度和羅嗦的API,建議你升級為fastjson,fastjson可以完全相容json-lib的序列化格式。

import  com.alibaba.fastjson.JSON;

import  com.alibaba.fastjson.serializer.JSONLibDataFormatSerializer;

import  com.alibaba.fastjson.serializer.JSONSerializerMap;

import  com.alibaba.fastjson.serializer.SerializerFeature;

private static final SerializeConfig  config;

static  {

    config = new  SerializeConfig();

    config.put(java.util.Date.class, new JSONLibDataFormatSerializer()); // 使用和json-lib相容的日期輸出格式

private  static  final  SerializerFeature[] features = {

SerializerFeature.WriteMapNullValue// 輸出空置欄位

        SerializerFeature.WriteNullListAsEmpty// list欄位如果為null,輸出為[],而不是null

        SerializerFeature.WriteNullNumberAsZero// 數值欄位如果為null,輸出為0,而不是null

        SerializerFeature.WriteNullBooleanAsFalse// Boolean欄位如果為null,輸出為false,而不是null

        SerializerFeature.WriteNullStringAsEmpty // 字元型別欄位如果為null,輸出為"",而不是null

  };

// 序列化為和JSON-LIB相容的字串

public static String toCompatibleJSONString(Object object) {

    return  JSON.toJSONString(object, config, features);

}

通過上面程式碼中的toCompatibleJSONString方法,你就可以實現完全相容json-lib了。

反序列化

反序列化就是把JSON格式的文字轉化為Java Bean物件。

指定Class資訊反序列化

通過指定型別資訊,可以很方便的將"JSON文字"反序列化為"Java Bean"物件,例如:

String text = ...; // {"r":255,"g":0,"b":0,"alpha":255}

Color color = JSON.parseObject(text, Color.class);

型別集合的反序列化

這個介面類似於parseObject

String text = ...; // [{ ... }, { ... }]

List<User> users = JSON.parseArray(text, User.class);

泛型的反序列化

如果你需要返回一個帶泛型的物件,例如List<User>、Map<String, User>,你可以使用TypeReference來傳入型別資訊。

String text = ...; // {"name":{"name":"ljw",age:18}}

Map<String, User> userMap = JSON.parseObject(text, new TypeReference<Map<String, User>>(){});

組合型別集合的反序列化

比如在網路協議中,經常會存在這樣的組合:

[{/*header*/}, {/*body*/}]

fastjson對這種結構的反序列化有專門支援。

String text = ...; // [{/* header */}, {/* body */}]

Type[] types = new  Type[]{Header.class, Body.class};

List<Object> list = JSON.parseArray(text, types);

Header header = (Header) list.get(0);

Body body = (Body) list.get(1);

使用@JSONCreator來指定建構函式來建立物件

如果你的JavaBean沒有預設建構函式,可以使用@JSONCreator來指定建構函式

public static class Entity {

    private  final  int     id; //應該用Integer才符合規範

    private  final  String name;

    @JSONCreator

    public  Entity(@JSONField(name = "id") int  id, @JSONField(name = "name") String name){

        this.id = id;

        this.name = name;

    }

    public  int  getId() { return  id; }

    public  String getName() { return  name; }

}

把JSON文字反序列化為一個原型介面

public static interface Bean { //介面

    int  getId();

    void  setId(int  value);

    String getName();

    void  setName(String value);

}

String text = "{\"id\":123, \"name\":\"chris\"}";

Bean bean = JSON.parseObject(text, Bean.class);

// 按介面呼叫

Assert.assertEquals(123, bean.getId());

Assert.assertEquals("chris", bean.getName());

bean.setId(234);

Assert.assertEquals(234, bean.getId());


。。。未完,待續