Jackson的用法例項分析

NO IMAGE

通俗的來說,Jackson是一個 Java 用來處理 JSON 格式資料的類庫,其效能非常好。本文就來針對Jackson的用法做一個較為詳細的例項分析。具體如下:

一、簡介

Jackson具有比較高的序列化和反序列化效率,據測試,無論是哪種形式的轉換,Jackson > Gson > Json-lib,而且Jackson的處理能力甚至高出Json-lib近10倍左右,且正確性也十分高。相比之下,Json-lib似乎已經停止更新,最新的版本也是基於JDK15,而Jackson的社群則較為活躍。
下面,結合例項來對Jackson的用法進行簡單介紹。

二、使用

Jackson提供了很多類和方法,而在序列化和反序列化中使用的最多的類則是ObjectMapper這個類,此類比較類似於Json-lib中JsonObject和ArrayObject。此類中提供了readTree(),readValue(),writeValueAsString()等方法用於轉換。具體關於此類的說明文件地址是:http://jackson.codehaus.org/1.7.9/javadoc/org/codehaus/jackson/map/ObjectMapper.html。

為了避免重複描述,下面中所涉及到的objectMapper均是來至於ObjectMapper objectMapper = new ObjectMapper()。下面將按照序列化和反序列化兩個方面來簡單介紹用法。

1.序列化

① 對java自帶類進行序列化

測試例子


List list=new ArrayList();
list.add(1);
list.add(2);
list.add(3);

實現序列化:


String teststringlist=objectMapper.writeValueAsString(list);
System.out.println(teststringlist);

在控制檯輸出的結果是:


[1,2,3]

結論:

Jackson對一般型別的序列化是能簡單實現的。

②對自定義類的序列化

測試例子:


public class student {
private int age=10;
private String name="hhh"; 
public String[] list={"hao","haouhao","keyi"};
public Date time=new Date();
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

為使例子更具有通用性,此類中包含了值型別int,引用型別String,String[],還包含了日期型別Date。
實現序列化


student st=new student();
String teststringstu=objectMapper.writeValueAsString(st);
System.out.println(teststringstu);

在控制檯輸出的結果是:


{"list":["hao","haouhao","keyi"],"time":1375429228382,"name":"hhh","age":10}

結論:

通過輸出,可見轉換得到的Json串是符合格式的。但是,時間的表示有點不符合標準。下面將介紹對時間格式的修改。

③對時間格式的定義

Jackson有自己的預設時間格式,即timestamps形式,其效果即如上結果所顯示的(例如:1375429228382)。如果想設定此格式是無效,通過


objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false)

便可設定,這樣將使時間生成使用所謂的使用 [ISO-8601 ]-compliant notation, 輸出類似如下格式的時間: “1970-01-01T00:00:00.000 0000″。

當然,也可以自定義輸出的時間格式。

自定義時間格式的實現

例子還採用上面所介紹的student類。


student st=new student();
java.text.DateFormat myFormat = new java.text.SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
objectMapper.getSerializationConfig().setDateFormat(myFormat);
String teststringstu=objectMapper.writeValueAsString(st);
System.out.println(teststringstu);

控制檯上輸出的記過是:


{"list":["hao","haouhao","keyi"],"time":"2013-08-02 03:48:20","name":"hhh","age":10}

結論:

可見時間輸出格式變成了我們想要的了。在Jackson中定義時間輸出格式的方法比在Json-lib中對時間格式的定義簡便很多。

④ 另一種序列化方法

實現序列化

所用例子依然是之前的student類。


student st=new student();
JsonGenerator jsonGenerator = objectMapper.getJsonFactory().createJsonGenerator(System.out, JsonEncoding.UTF8);
jsonGenerator.writeObject(st); 
System.out.println();

控制檯上的輸出結果是:


{"list":["hao","haouhao","keyi"],"time":1375429228382,"name":"hhh","age":10}

結論:

此方法同樣可以得到上面方法的值。但是注意此方法中的這個函式:createJsonGenerator(),它需要兩個引數,一個是OutputStream型別引數,一個是JsonEncoding型別引數。通過這兩個引數,我們可以瞭解到,此方法不僅可以將Json直接寫入網路流,還可以將Json寫入檔案流或者記憶體流。所以用途更廣。

2. 反序列化

①一次性反序列化

此方法中主要利用ObjectMapper提供的<testJsonClass> readValue(String content, Class<testJsonClass> valueType)方法。此方法需要輸入Json串以及對應的需要填充的類的Class,返回填充後的類。
將Json串解析到自定義類中

當Json串為:


String test1="{"objectID":357,"geoPoints":[{"x":504604.59802246094,"y":305569.9150390625}]}"

的時候。

首先自定義一個類:


public class testJsonClass
{
public int objectID;
public List geoPoints=new ArrayList();
}

然後利用下面段程式碼將Json反序列化到此類中:


testJsonClass testClass= objectMapper.readValue(test1, testJsonClass.class);

利用


System.out.println(testClass.objectID);
System.out.println(testClass.geoPoints)

可以在控制檯上看到輸出的值為:


357
[{x=504604.59802246094, y=305569.9150390625}]

將Json串反序列化到系統自帶的類中
當Json串是


String json = "{"error":0,"data":{"name":"ABC","age":20,"phone":{"home":"abc","mobile":"def"},"friends":[{"name":"DEF","phone":{"home":"hij","mobile":"klm"}},{"name":"GHI","phone":{"home":"nop","mobile":"qrs"}}]},"other":{"nickname":[]}}"。

用系統自帶的Map定義一個變數:Map<String, Map<String, Object>>  maps。然後利用maps = objectMapper.readValue(json, Map.class)便可將Json反序列化到變數maps中。
通過


System.out.println(maps.get("error"));
System.out.println((Object)(maps.get("data").get("phone")))

可在控制檯中得到下面的結果:


0
{home=abc, mobile=def}

②漸次反序列化

此方法更靈活,可以只將使用者感興趣的Json串資訊值提取出來。主要利用ObjectMapper提供的readTree和Jackson提供的JsonNode類來實現。

測試例子


String test="{"results":[{"objectID":357,"geoPoints":[{"x":504604.59802246094,"y":305569.9150390625}]},{"objectID":358,"geoPoints":[{"x":504602.2680053711,"y":305554.43603515625}]}]}";

此Json串比較複雜,包含了巢狀陣列的形式,具有通用性。

實現反序列化


JsonNode node= objectMapper.readTree(test);   //將Json串以樹狀結構讀入記憶體
JsonNode contents=node.get("results");//得到results這個節點下的資訊
for(int i=0;i<contents.size();i  ) //遍歷results下的資訊,size()函式可以得節點所包含的的資訊的個數,類似於陣列的長度
{
System.out.println(contents.get(i).get("objectID").getIntValue()); //讀取節點下的某個子節點的值
JsonNode geoNumber=contents.get(i).get("geoPoints");
for(int j=0;j<geoNumber.size();j  )   //迴圈遍歷子節點下的資訊
{
System.out.println(geoNumber.get(j).get("x").getDoubleValue() " " geoNumber.get(j).get("y").getDoubleValue());
}
}

在控制檯下輸出的結果是:


357
504604.59802246094 305569.9150390625
358
504602.2680053711 305554.43603515625

結論:

此方法類似於XML解析中的DOM方式解析,其好處是結構明細,便於提取想要的資訊。當然,其缺點也和此方法一樣:耗時費空間。

三.總結

Jackson關於Json的操作主要如上所示,其方法使用起來很便利,而且也很靈活,即提供了一次性完成的操作,也提供了可以按需讀取資訊的操作。並且Jackson的功能很齊全,可以對序列化和反序列化進行多種細節的控制,例如註解功能和對於Hibernate的延遲注入功能以及設定時間格式功能等,因為這些功能目前不太需要,所以仔細研究留待以後。同時,Jackson還支援對XML的一系列序列化和反序列化的操作,其思路與解析Json的大致相同。
對於Jackson目前的缺點,網上有人測試所比Json-lib更佔記憶體一些。而利用空間換時間,一般是值得的。

您可能感興趣的文章:

解析Java的Jackson庫中物件的序列化與資料泛型繫結例項解析Java的Jackson庫中的資料繫結Java的Jackson庫的使用及其樹模型的入門學習教程解析Java的Jackson庫中Streaming API的使用使用Jackson來實現Java物件與JSON的相互轉換的教程如何讓Jackson JSON生成的資料包含的中文以unicode方式編碼舉例講解Java的Jackson庫中ObjectMapper類的使用