欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Jackson的用法实例分析

程序员文章站 2024-02-29 19:37:16
通俗的来说,jackson是一个 java 用来处理 json 格式数据的类库,其性能非常好。本文就来针对jackson的用法做一个较为详细的实例分析。具体如下: 一、简...

通俗的来说,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更占内存一些。而利用空间换时间,一般是值得的。