有效選擇七個關於 Java 的 JSON 開源類庫

簡介java

JSON是JavaScriptObjectNotation的縮寫,是一種輕量級的數據交換形式,是一種XML的替代方案,並且比XML更小,更快並且更易於解析。由於JSON描述對象的時候使用的是JavaScript語法,它是語言和平臺獨立的,而且這些年許多JSON的解析器和類庫被開發出來。在這篇文章中,咱們將會展現7種JavaJSON類庫。基本上,咱們將會試着把Java對象轉換JSON格式而且存儲到文件,而且反向操做,讀JSON文件轉換成一個對象。爲了讓文章更有意義,咱們將會測量每一種JSON類庫在不一樣狀況下的處理速度。apache

(一)類庫介紹及其使用json

(1)使用Jackson類庫數組

第一個介紹的是Jackson類庫,Jackson庫是一個「旨在爲開發者提供更快,更正確,更輕量級,更符合人性思惟」的類庫。Jackson爲處理JSON格式提供了三種模型的處理方法。架構

一、流式API或者增量解析/產生(incrementalparsing/generation):讀寫JSON內容被做爲離散的事件。app

二、樹模型:提供一個可變內存樹表示JSON文檔。maven

三、數據綁定(Databinding):實現JSON與POJO(簡單的Java對象(PlainOldJavaObject))的轉換ide

咱們感興趣的是Java對象與JSON的轉換,所以,咱們將集中於第三種處理方法。首先咱們須要下載Jackson。Jackson的核心功能使用三個類庫,分別是jackson-core-2.3.1,jackson-databind-2.3.1和jackson-annotations-2.3.1;三個類庫的下載都來自於Maven倉庫,給出地址:性能

http://repo1.maven.org/maven2/com/fasterxml/jackson/測試

(譯者注:在http://repo1.maven.org/maven2/com/fasterxml/jackson/core/中,正好是三個類庫的文件夾)

如今,讓咱們來工做吧,爲了從Java對象中得到一個一個複雜的JSON對象,咱們將會使用下面的類去構造一個對象。一樣的Java對象將會被用於這篇文章的全部的類庫中。

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

 

 

publicclassJsonThirdObject{

privateintage=81;

privateStringname="MichaelCaine";

privateList<String>messages;

publicJsonThirdObject(){

this.messages=newArrayList<String>(){

{

add("Youwouldn'thitamanwithnotrousers..");

add("Atthispoint,I'dsetyouupwitha..");

add("Youknow,yourbobbydangler,gigglestick,..");

}

};

}

//Getterandsetter

}

publicclassJsonSecondObject{

privateintage=83;

privateStringname="ClintEastwood";

privateJsonThirdObjectjsnTO=newJsonThirdObject();

privateList<String>messages;

publicJsonSecondObject(){

this.messages=newArrayList<String>(){

{

add("ThisistheAK-47assault..");

add("Areyoufeelinglucky..");

add("Whenanakedman'schasinga..");

}

};

}

//Getterandsetter

}

publicclassJsonFirstObject{

privateintage=76;

privateStringname="MorganFreeman";

privateJsonSecondObjectjsnSO=newJsonSecondObject();

privateList<String>messages;

publicJsonFirstObject(){

this.messages=newArrayList<String>(){

{

add("Ionceheardawisemansay..");

add("Well,whatisittoday?More..");

add("Bruce...I'mGod.Circumstanceshave..");

}

};

}

//Getterandsetter

}

publicclassJson{

privateintage=52;

privateStringname="JimCarrey";

privateJsonFirstObjectjsnFO=newJsonFirstObject();

privateList<String>messages;

publicJson(){

this.messages=newArrayList<String>(){

{

add("Hey,maybeIwillgiveyou..");

add("Excuseme,I'dliketo..");

add("Brainfreeze.AlrightyThenIjust..");

}

};

}

//Getterandsetter

}

上面的Java對象轉換成JSON格式是下面這樣的。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

 

{

"age":52,

"name":"JimCarrey",

"jsnFO":{

"age":76,

"name":"MorganFreeman",

"jsnSO":{

"age":83,

"name":"ClintEastwood",

"jsnTO":{

"age":81,

"name":"MichaelCaine",

"messages":[

"Youwouldn'thitaman..",

"Atthispoint,I'dsetyou..",

"Youknow,yourbobbydangler.."

]

},

"messages":[

"ThisistheAK-47assault..",

"Areyoufeelinglucky..",

"Whenanakedman'schasinga.."

]

},

"messages":[

"Ionceheardawiseman..",

"Well,whatisittoday?More..",

"Bruce...I'mGod.Circumstanceshave.."

]

},

"messages":[

"Hey,maybeIwillgiveyouacall..",

"Excuseme,I'dliketoaskyouafew..",

"Brainfreeze.AlrightyThenIjustheard.."

]

}

如今,讓咱們來看看怎麼樣把Java對象轉換成JSON而且寫入文件。Jackson使用一個ObjectMapper功能,咱們第一步要作的是:

?

1

2

3

JsonjsonObj=newJson();

ObjectMappermapper=newObjectMapper();

而後,咱們將會使用這個ObjectMapper直接寫入值到文件。

?

1

2

3

4

5

6

7

 

System.out.println("ConvertJavaobjecttoJSONformatandsavetofile");

try{

mapper.writeValue(newFile("c:jackson.json"),jsonObj);

}catch(JsonGenerationExceptione){

}catch(JsonMappingExceptione){

}catch(IOExceptione){

}

如今,咱們有了一個JSON文件,可是,怎麼樣轉回Java對象呢?咱們能夠這樣作:

?

1

2

3

4

5

6

7

8

System.out.println("ReadJSONfromfile,convertJSONbacktoobject");

try{

jsonObj=mapper.readValue(newFile("c:jackson.json"),Json.class);

}catch(JsonGenerationExceptione){

}catch(JsonMappingExceptione){

}catch(IOExceptione){

}

從上面的例子咱們知道了JSON和Java對象的相互轉換,在try-catch中總共也就兩行,看起來不錯是吧,可是它快麼?咱們將會在後面的文章中揭曉。

(2)使用Google-Gson類庫

第二種就是Google-Gson,咱們當即開始討論Gson,你或許更喜歡他的全名Google-Gson。Gson能實現Java對象和JSON之間的相互轉換。甚至都不須要註釋。Gson的特色:

1)提供簡單的toJson()方法和fromJson()去實現相互轉換。

2)能夠從JSON中轉換出以前存在的不可改變的對象。

3)擴展提供了Java泛型。

4)支持任意複雜的對象。

Gson就須要一個.jar文件,gson-2.2.4.jar,能夠經過http://code.google.com/p/google-gson/downloads/list下載。下面是例子,把Java對象轉換成JSON。

?

1

2

3

4

5

6

7

8

JsonjsonObj=newJson();

Gsongson=newGson();

System.out.println("ConvertJavaobjecttoJSONformatandsavetofile");

try(FileWriterwriter=newFileWriter("c:gson.json")){

writer.write(gson.toJson(jsonObj));

}catch(IOExceptione){

}

JSON轉換成Java對象:

?

1

2

3

4

5

6

 

System.out.println("ReadJSONfromfile,convertJSONstringbacktoobject");

try(BufferedReaderreader=newBufferedReader(newFileReader("c:gson.json"))){

jsonObj=gson.fromJson(reader,Json.class);

}catch(FileNotFoundExceptione){

}catch(IOExceptione){

}

上面就是咱們全部須要作的,接下來咱們能夠對jsonObj做進一步處理。當調用JSON操做的時候,由於Gson的實例化對象沒有維持任何狀態,咱們能夠重複使用一個對象爲多個JSON序列化和反序列化操做。

(3)使用JSON-lib類庫

JSON-lib類庫是基於DouglasCrockford的工做成果,能轉換bean,map,集合(collection),java數組和XML轉換成JSON並能反向轉換成beans和動態bean(DynaBean)。JSON-lib類庫的下載地址:http://sourceforge.net/projects/json-lib/files/下面這些是依賴文件

·jakartacommons-lang2.6

·jakartacommons-beanutils1.9.1

·jakartacommons-collections3.2.1

·jakartacommons-logging1.1.3

·ezmorph1.0.6

(譯者注:DouglasCrockfordWeb開發領域最知名的技術權威之一,ECMAJavaScript2.0標準化委員會委員。被JavaScript之父BrendanEich稱爲JavaScript的大宗師(Yoda)。曾任Yahoo!資深JavaScript架構師,現任PayPal高級JavaScript架構師。他是JSONJSLintJSMinADSafe的創造者,也是名著《JavaScript:TheGoodParts》(中文版《JavaScript語言精粹》)的做者。撰寫了許多廣爲流傳、影響深遠的技術文章,包括「JavaScript:世界上最被誤解的語言」。DouglasCrockford曾在著名的Lucasfilm電影公司任技術總監;在Paramount(派拉蒙)公司任新媒體高級總監;communities社區創始人兼CEOState軟件公司CTO2012.05.14Paypal宣佈DouglasCrockford加入Paypal)

一樣,讓咱們來把Java對象轉成JSON。

?

1

2

3

4

5

6

7

8

 

JsonjsonObj=newJson();

JSONObjectjson;

System.out.println("ConvertJavaobjecttoJSONformatandsavetofile");

try(FileWriterwriter=newFileWriter("c:json-lib.json")){

json=JSONObject.fromObject(jsonObj);

json.write(writer);

}catch(IOExceptione){

}

JSON轉Java對象

?

1

2

3

4

5

 

System.out.println("ReadJSONfromfile,convertJSONstringbacktoobject");

try(BufferedReaderreader=newBufferedReader(newFileReader("c:json-lib.json"))){

jsonObj=(Json)JSONObject.toBean(JSONObject.fromObject(reader),Json.class);

}catch(IOExceptionex){

}

這裏有個問題,這些依賴關係會影響到性能嗎?文章在下面揭曉。

(4)使用Flexjson類庫

Flexjson是一個輕量級的庫,能序列化和反序列化Java對象和JSON,容許深層和淺層對象的拷貝。深度拷貝意味着一個被Flexjson序列化的對象,它能讓對象作到相似於延遲加載(lazy-loading)的技術,能讓咱們在對對象有須要時才提取。當咱們想把整個對象寫入到文件時,這不是一個好的狀況,可是它知道須要纔去作時,這是很好的。

Flexjson下載地址:http://sourceforge.net/projects/flexjson/files/它不須要其餘庫就能夠工做。下面是例子:Java對象轉JSON。

?

1

2

3

4

5

6

7

 

JsonjsonObj=newJson();

JSONSerializerserializer=newJSONSerializer();

System.out.println("ConvertJavaobjecttoJSONformatandsavetofile");

try(FileWriterwriter=newFileWriter("c:flexjson.json")){

serializer.deepSerialize(jsonObj,writer);

}catch(IOExceptione){

}

JSON轉Java對象

?

1

2

3

4

5

6

 

System.out.println("ReadJSONfromfile,convertJSONstringbacktoobject");

try(BufferedReaderreader=newBufferedReader(newFileReader("c:flexjson.json"))){

jsonObj=newJSONDeserializer<Json>().deserialize(reader);

}catch(FileNotFoundExceptione){

}catch(IOExceptione){

}

簡單有效是吧!

(5)使用Json-io類庫

json-io有兩個主要的類,一個讀和一個寫,排除了使用ObjectInputStream和ObjectOutputStream兩個類去讀寫。Json-io能序列化任意的Java對象圖(graph)轉變成JSON,而且能記憶完整的語義圖(graphsemantics)和對象類型。下載地址:MavenCentralRepository

它不須要其餘依賴。

例子:Java對象轉JSON

?

1

2

3

4

5

6

 

JsonjsonObj=newJson();

System.out.println("ConvertJavaobjecttoJSONformatandsavetofile");

try(JsonWriterwriter=newJsonWriter(newFileOutputStream("c:json-io.json"))){

writer.write(jsonObj);

}catch(IOExceptione){

}

JSON轉Java對象

?

1

2

3

4

5

6

 

System.out.println("ReadJSONfromfile,convertJSONstringbacktoobject");

try(JsonReaderreader=newJsonReader(newFileInputStream(newFile("c:json-io.json")))){

jsonObj=(Json)reader.readObject();

}catch(FileNotFoundExceptione){

}catch(IOExceptione){

}

它的文檔上說,Json-io比JDK的ObjectInputStream和ObjectOutputStream的序列化操做要快,咱們將會在後面的文章中說明。

(6)使用Genson類庫

Genson是一個可擴展的,可伸縮的,易於使用的開源庫。除此以外,Genson完整支持了泛型,支持JSON在JAX-RS的實現,支持JAXB的註釋(annotation)和類型(types),而且容許序列化和反序列化擁有複雜關鍵字的map。

下載地址:http://code.google.com/p/genson/downloads/list,它沒有任何依賴。

例子:Java對象轉JSON

?

1

2

3

4

5

6

7

 

JsonjsonObj=newJson();

Gensongenson=newGenson();

System.out.println("ConvertJavaobjecttoJSONformatandsavetofile");

try(FileWriterwriter=newFileWriter("c:genson.json")){

writer.write(genson.serialize(jsonObj));

}catch(IOException|TransformationExceptione){

}

JSON轉Java對象

?

1

2

3

4

5

6

 

System.out.println("ReadJSONfromfile,convertJSONstringbacktoobject");

try(BufferedReaderreader=newBufferedReader(newFileReader("c:genson.json"))){

jsonObj=genson.deserialize(reader,Json.class);

}catch(FileNotFoundExceptione){

}catch(IOException|TransformationExceptione){

}

(7)使用JSONiJ類庫

最後一個討論的是JSONiJ。JSONiJ是JSON的解析器,一個JPath和Marshaller的實現,能實現Java對象和JSON的相互轉換。下載地址:https://bitbucket.org/jmarsden/jsonij/downloads

它不須要任何依賴。

例子:Java對象轉JSON

?

1

2

3

4

5

6

 

JsonjsonObj=newJson();

System.out.println("ConvertJavaobjecttoJSONformatandsavetofile");

try(FileWriterwriter=newFileWriter("c:jsonij.json")){

writer.write(JSONMarshaler.marshalObject(jsonObj).toJSON());

}catch(IOException|JSONMarshalerExceptione){

}

JSON轉Java對象

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

 

System.out.println("ReadJSONfromfile,convertJSONstringbacktoobject");

try(BufferedReaderreader=newBufferedReader(newFileReader("c:jsonij.json"))){

JSONjson=JSON.parse(reader);

//NowweneedtoparsetheJSONObjectobjectandputvaluesback

//toourJsonobject

for(Fieldfield:jsonObj.getClass().getDeclaredFields()){

try{

field.setAccessible(true);

field.set(field.getName(),json.get(field.getName()));

}catch(IllegalArgumentException|IllegalAccessExceptione){

}

}

}catch(FileNotFoundExceptione){

}catch(IOException|ParserExceptione){

}

看起來JSONiJ須要的代碼多些,性能怎麼樣,咱們看下面。

(二)基準測試

如今咱們要來看看性能了,測試硬件配置:IntelCorei5laptopwith2.50GHz單通道DDR3RAM4G,軟件配置:Windows7Ultimate64-bitSP1

基準測試運行同樣的虛擬機(JVM),在測試以前,每個類庫都有一個熱身,去限制內存使用的形成的影響,用一個顯式調用垃圾收集器。下面的圖表表明的是序列化和反序列化JSON數據以毫秒級使用50次迭代和10次熱身(warm-up)迭代的平均的時間。

(譯者注:紅色爲序列化(Java對象轉JSON),藍色爲反序列化(JSON轉Java對象))

上面的圖表顯示,Flexjson序列化小數據時是最快的,而JSON-lib是最慢的。反序列化的時候,Gson最快,JSON-lib仍是最慢的。

下面的圖表表明的是咱們的數據在287kb時,序列化和反序列化所花費的平均時間。

這張圖顯示,咱們對少許的數據操做時,最快的是Gson,以後的是Genson和Flexjson。

當變成大數據時,結果變得很不同。在下面的圖表中,使用的是108Mb的數據,在序列化的時候,Jackson變成了最快的,Flexjson變成第二快。在反序列化的時候,JSON-lib變成了最快的,以前在處理小數據時,它是最慢的,第二快的是Jackson。

 

下面的圖表,顯示的是處理更大一點的數據時,咱們應該使用Jackson和JSON-lib。

另一個重要的測試是關於.jar包的大小。這對於移動端的開發很重要,咱們從下圖中看到,json-io最小,以後依次是Flexjson和JSONiJ:

(三)結論

在這篇文章中,咱們知道了七種方式來實現Java對象和JSON之間的互相轉換。以及哪個類庫更快,哪個更慢,在什麼狀況下使用等。做爲結論,若是你在你的應用中是想使用小一點的數據量,你應該使用Flexjson或者Gson,若是你須要大的數據量你應該考慮Jackson和JSON-lib。

相關文章
相關標籤/搜索