有效选择七个关于 Java 的 JSON 开源类库

简介

JSON是JavaScriptObjectNotation的缩写,是一种轻量级的数据交换形式,是一种XML的替代方案,而且比XML更小,更快而且更易于解析。因为JSON描述对象的时候使用的是JavaScript语法,它是语言和平台独立的,并且这些年许多JSON的解析器和类库被开发出来。在这篇文章中,我们将会展示7种JavaJSON类库。基本上,我们将会试着把Java对象转换JSON格式并且存储到文件,并且反向操作,读JSON文件转换成一个对象。为了让文章更有意义,我们将会测量每一种JSON类库在不同情况下的处理速度。

(一)类库介绍及其使用

(1)使用Jackson类库

第一个介绍的是Jackson类库,Jackson库是一个“旨在为开发者提供更快,更正确,更轻量级,更符合人性思维”的类库。Jackson为处理JSON格式提供了三种模型的处理方法。

1、流式API或者增量解析/产生(incrementalparsing/generation):读写JSON内容被作为离散的事件。

2、树模型:提供一个可变内存树表示JSON文档。

3、数据绑定(Databinding):实现JSON与POJO(简单的Java对象(PlainOldJavaObject))的转换

我们感兴趣的是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。

转载于:https://my.oschina.net/u/3346994/blog/858760

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值