【Jackson】Jackson和Jackson的用法实例分析

既看既用(ObjectMapper):

1、下载jackson-all-1.7.3.jar包,工程中java buildpath 设置中,add extral JAS中添加该jar包,代码中导入:import org.codehaus.jackson.map.ObjectMapper

2、同时复制一份放入到tomcat的lib目录中,


1、Java对象转换为JSON:

User user=new User(); //Java Object

ObjectMapper mapper = new ObjectMapper();

mapper.writeValueAsString(user); //返回字符串JSO

 


//输出格式化后的字符串看看对不对(有性能损耗):mapper.defaultPrettyPrintingWriter().writeValueAsString(user);

mapper.writeValue(new File("c:\\user.json"), user); //指定文件写入


//设置序列化配置(全局),设置序列化时不输出空值.

sharedMapper.getSerializationConfig().setSerializationInclusion(Inclusion.NON_NULL);

 

2、JSON反序列化为Java对象:

ObjectMapper mapper = new ObjectMapper();

//解析器支持解析单引号

mapper.configure(Feature.ALLOW_SINGLE_QUOTES,true);

//解析器支持解析结束符

mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS,true);

HashMap jsonMap = mapper.readValue(json,HashMap.class); //转换为HashMap对象


 

 

(一个问题:json序列话后是二进制数据还是字符串?--》序列话和二进制序列化)

 

“JSON序列化 是将对象的属性以键值对的形式组织成字符串(一个编码过程),显然体积会增大很多。
而且解码后也不能直接还原回原来的对象
二进制序列化 是将对象的内存映射抽取出来形成字符串,还原时只有一个重新分配内存的过程。还原后依然还是你原来的对象

将二进制序列化后的串写入文件,就可以认为他是数据库中的一个表(专用的而已)
如果将你的对象细分成若干个子对象,分别对各子对象做二进制序列化,并以某种格式保存在同一个文件中。
再配上管理方法,那么你就已经实现了自己的 NOSQL 了 ”

 



2说明

首先我们先看一下核心模块

 

  其实核心模块就是扩展模块构建的基础,据统计,截止到2.7版本为止一共有3个核心模块,下面我们一起来看一下:

 

  第一个是:Streaming:jackson-corejar,定义了底层的streamingAPI和实现了Json特性。

 

  第二个是:Annotations:jackson-annotationsjar,包含了标准的Jackson注解。本文暂不介绍。

 

  第三个是:Databind:jackson-databindjar,实现了数据绑定和对象序列化,它依赖于streaming和annotations的包。

  

上面是3个jackson分开包,有个包集合是:jackson-all-1.7.3.jar 

(导入类的路径:import org.codehaus.jackson.map.ObjectMapper

 

Jackson为我们提供了三种可选的Json处理方法:数据绑定(DataBinding),流式API(StreamingAPI)和树模型(TreeModel)。

 

一.1 文章

这篇文章主要介绍了Jackson的用法实例分析,用于处理Java的json格式数据。

通俗的来说,Jackson是一个 Java 用来处理 JSON 格式数据的类库,其性能非常好。本文就来针对Jackson的用法做一个较为详细的实例分析。具体如下:

地址:http://www.jb51.net/article/53289.htm

 

一.1.1 简介

 

Jackson具有比较高的序列化和反序列化效率,据测试,无论是哪种形式的转换,Jackson > Gson > Json-lib,而且Jackson的处理能力甚至高出Json-lib近10倍左右,且正确性也十分高。相比之下,Json-lib似乎已经停止更新,最新的版本也是基于JDK15,而Jackson的社区则较为活跃。

下面,结合实例来对Jackson的用法进行简单介绍。

 

一.1.2 使用

 

Jackson提供了很多类和方法,而在序列化和反序列化中使用的最多的类则是ObjectMapper这个类,此类比较类似于Json-libJsonObjectArrayObject。此类中提供了readTree()readValue(),writeValueAsString()等方法用于转换。具体关于此类的说明文档地址是:http://jackson.codehaus.org/1.7.9/javadoc/org/codehaus/jackson/map/ObjectMapper.html

 

为了避免重复描述,下面中所涉及到的objectMapper均是来至于ObjectMapper objectMapper = new ObjectMapper()。下面将按照序列化和反序列化两个方面来简单介绍用法。

 

一.1.2.1 序列化

 

1. java自带类进行序列化

 

测试例子

List list=new ArrayList();

list.add(1);

list.add(2);

list.add(3);

 

实现序列化:

String  myjson=objectMapper.writeValueAsString(list);

System.out.println(myjson);

 

在控制台输出的结果是:

 [1,2,3]

 

结论:

 

Jackson对一般类型的序列化是能简单实现的。

 

2. 对自定义类的序列化

 

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,引用类型StringString[],还包含了日期类型Date

实现序列化

student st=new student();

String json=objectMapper.writeValueAsString(st);

System.out.println(json);

 

在控制台输出的结果是:

 

 

{"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 ;

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写入文件流或者内存流。所以用途更广。

 

反序列化

 

一次性反序列化

 

此方法中主要利用ObjectMapper提供的 readValue(String content, Class 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)

 

可以在控制台上看到输出的值为:

 

 [{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>  maps。然后利用maps = objectMapper.readValue(json, Map.class)便可将Json反序列化到变量maps中。

通过

System.out.println(maps.get("error"));

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

 

可在控制台中得到下面的结果:

{home=abc, mobile=def}

 

渐次反序列化

 

此方法更灵活,可以只将用户感兴趣的Json串信息值提取出来。主要利用ObjectMapper提供的readTreeJackson提供的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遍历results下的信息,size()函数可以得节点所包含的的信息的个数,类似于数组的长度

{

System.out.println(contents.get(i).get("objectID").getIntValue()); //读取节点下的某个子节点的值

JsonNode geoNumber=contents.get(i).get("geoPoints");

for(int j=0;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更占内存一些。而利用空间换时间,一般是值得的。

 

 

一.2 记忆

ObjectMapper类的writeValueAsStringvalueToTreereadTree等方法

 

ObjectMapper mapper = new ObjectMapper();

String  jsonStr=mapper.writeValueAsString(A);//A是任何一个自定的java类,或者是java类库的类如map   //得到的是一个json格式的String (字符型的json)

 

JsonNode jn=mapper.valueToTree(B);//B是任何一个自定的java类,或者是java类库的类如map //得到的是一个JsonNode类型(这个是Jackson框架jar包的一个类型)

 

JsonNode jn=mapper.readTree(C);//C是一个json格式String//得到的是一个JsonNode类型(这个是Jackson框架jar包的一个类型)

 

List list=mapper.readValue(D,List.class);//D是一个json格式String//得到的是一个List类型。

 

问:我怎么记住,每个方法得到的是什么?

记忆技巧:方法的最末的单词(即标红的位置)意思是什么,得到的就是什么。两者一样。

 

 

 

 

 

一.3 实例

 Student 类 (bean ---类内有操作本身的函数)

package com.jingshou.pojo;  

import java.util.Date;  


public class Student {  

  private int id;  

  private String name;  

  private Date birthDay;  

 

  public int getId() {  

     return id;  

  }  

  public void setId(int id) {  

     this.id = id;  

 }  

 public String getName() {  

        return name;  

    }  

public void setName(String name) {  

     this.name = name;  

   } 

    public Date getBirthDay() {  

        return birthDay;  

   }  

    public void setBirthDay(Date birthDay) {  

       this.birthDay = birthDay;  

    }  

  @Override  

   public String toString() {  

      return "Student [birthDay=" + birthDay + ", id=" + id + ", name="  

              + name + "]";  

   }  

}  

Class 班级类(bean ---类内有操作本身的函数)

package com.jingshou.pojo;

import java.util.List;


public class Class {

private String cname;

private List members;

public String getCname() {

return cname;

}

public void setCname(String cname) {

this.cname = cname;

}

public List getMembers() {

return members;

}

public void setMembers(List members) {

this.members = members;

}

 

public String toString(){

return "The Class Name is: " + cname + " " + "The members are: " + members;

 

}

 


 

}



JSON系列化和反序列化


package com.jingshou.jackson;


import java.io.IOException;

import java.util.ArrayList;

import java.util.Date;

import java.util.List;


import com.fasterxml.jackson.databind.ObjectMapper;

import com.jingshou.pojo.Class;

import com.jingshou.pojo.Student;


public class JacksonTest1 {


public static void main(String[] args) throws IOException {

Student student1 = new Student();  

student1.setId(5237);

student1.setName("jingshou");

student1.setBirthDay(new Date());

 

        ObjectMapper mapper = new ObjectMapper();

        

        // Convert object to JSON string

        String Json =  mapper.writeValueAsString(student1); //对象序列化JSON(字符数据)


        System.out.println("Change Object to JSON String: " + Json);

        

       // Convert Json string to Object

        Student student2 = mapper.readValue(Json, Student.class);//JSON(字符数据)反序列化为对象

        System.out.println(student2);

        

        // Create a student list add it to Bj

        Student student3 = new Student();  

        student3.setId(5117);  

        student3.setName("saiya");  

        student3.setBirthDay(new Date());  

  

        List stuList = new ArrayList();

        stuList.add(student1);

        stuList.add(student3);

        

        Class bj = new Class();

        bj.setCname("五年二班");

        bj.setMembers(stuList);

        

        String json2 = mapper.writeValueAsString(bj);

        System.out.println("The JSON from Class is: " + json2);

        

        Class bj2 = mapper.readValue(json2, Class.class);

        System.out.println(bj2);

        


}


}





二、Jackson支持3种使用方式:(原文:http://shensy.iteye.com/blog/1717776)

1、Data Binding:最方便使用.

(1)Full Data Binding:

Java代码   收藏代码【Jackson】Jackson和Jackson的用法实例分析
  1. private static final String MODEL_BINDING = "{"name":"name1","type":1}";  
  2.     public void fullDataBinding() throws Exception{  
  3.         ObjectMapper mapper = new ObjectMapper();  
  4.         Model user = mapper.readValue(MODEL_BINDING, Model.class);//readValue到一个实体类中.  
  5.         System.out.println(user.getName());  
  6.         System.out.println(user.getType());  
  7.     }  
private static final String MODEL_BINDING = "{"name":"name1","type":1}";
        public void fullDataBinding() throws Exception{
                ObjectMapper mapper = new ObjectMapper();
                Model user = mapper.readValue(MODEL_BINDING, Model.class);//readValue到一个实体类中.
                System.out.println(user.getName());
                System.out.println(user.getType());
        }

Model类:

Java代码   收藏代码【Jackson】Jackson和Jackson的用法实例分析
  1. private static class Model{  
  2.         private String name;  
  3.         private int type;  
  4.           
  5.         public String getName() {  
  6.             return name;  
  7.         }  
  8.         public void setName(String name) {  
  9.             this.name = name;  
  10.         }  
  11.         public int getType() {  
  12.             return type;  
  13.         }  
  14.         public void setType(int type) {  
  15.             this.type = type;  
  16.         }  
  17.     }  
private static class Model{
                private String name;
                private int type;
                
                public String getName() {
                        return name;
                }
                public void setName(String name) {
                        this.name = name;
                }
                public int getType() {
                        return type;
                }
                public void setType(int type) {
                        this.type = type;
                }
        }

(2)Raw Data Binding:

Java代码   收藏代码【Jackson】Jackson和Jackson的用法实例分析
  1.   
  2.     public void rawDataBinding() throws Exception{  
  3.         ObjectMapper mapper = new ObjectMapper();  
  4.         HashMap map = mapper.readValue(MODEL_BINDING,HashMap.class);//readValue到一个原始数据类型.  
  5.         System.out.println(map.get("name"));  
  6.         System.out.println(map.get("type"));  
  7.     }  
        public void rawDataBinding() throws Exception{
                ObjectMapper mapper = new ObjectMapper();
                HashMap map = mapper.readValue(MODEL_BINDING,HashMap.class);//readValue到一个原始数据类型.
                System.out.println(map.get("name"));
                System.out.println(map.get("type"));
        }

 (3)generic Data Binding:

Java代码   收藏代码【Jackson】Jackson和Jackson的用法实例分析
  1. private static final String GENERIC_BINDING = "{"key1":{"name":"name2","type":2},"key2":{"name":"name3","type":3}}";  
  2.     public void genericDataBinding() throws Exception{  
  3.         ObjectMapper mapper = new ObjectMapper();  
  4.         HashMap modelMap = mapper.readValue(GENERIC_BINDING,new TypeReference>(){});//readValue到一个范型数据中.  
  5.         Model model = modelMap.get("key2");  
  6.         System.out.println(model.getName());  
  7.         System.out.println(model.getType());  
  8.     }  
private static final String GENERIC_BINDING = "{"key1":{"name":"name2","type":2},"key2":{"name":"name3","type":3}}";
        public void genericDataBinding() throws Exception{
                ObjectMapper mapper = new ObjectMapper();
                HashMap modelMap = mapper.readValue(GENERIC_BINDING,new TypeReference>(){});//readValue到一个范型数据中.
                Model model = modelMap.get("key2");
                System.out.println(model.getName());
                System.out.println(model.getType());
        }

2、Tree Model:最灵活。

Java代码   收藏代码【Jackson】Jackson和Jackson的用法实例分析
  1. private static final String TREE_MODEL_BINDING = "{"treekey1":"treevalue1","treekey2":"treevalue2","children":[{"childkey1":"childkey1"}]}";  
  2.     public void treeModelBinding() throws Exception{  
  3.         ObjectMapper mapper = new ObjectMapper();  
  4.         JsonNode rootNode = mapper.readTree(TREE_MODEL_BINDING);  
  5.         //path与get作用相同,但是当找不到该节点的时候,返回missing node而不是Null.  
  6.         String treekey2value = rootNode.path("treekey2").getTextValue();//  
  7.         System.out.println("treekey2value:" + treekey2value);  
  8.         JsonNode childrenNode = rootNode.path("children");  
  9.         String childkey1Value = childrenNode.get(0).path("childkey1").getTextValue();  
  10.         System.out.println("childkey1Value:"+childkey1Value);  
  11.           
  12.         //创建根节点  
  13.         ObjectNode root = mapper.createObjectNode();  
  14.         //创建子节点1  
  15.         ObjectNode node1 = mapper.createObjectNode();  
  16.         node1.put("nodekey1",1);  
  17.         node1.put("nodekey2",2);  
  18.         //绑定子节点1  
  19.         root.put("child",node1);  
  20.         //数组节点  
  21.         ArrayNode arrayNode = mapper.createArrayNode();  
  22.         arrayNode.add(node1);  
  23.         arrayNode.add(1);  
  24.         //绑定数组节点  
  25.         root.put("arraynode", arrayNode);  
  26.         //JSON读到树节点  
  27.         JsonNode valueToTreeNode = mapper.valueToTree(TREE_MODEL_BINDING);  
  28.         //绑定JSON节点  
  29.         root.put("valuetotreenode",valueToTreeNode);  
  30.         //JSON绑定到JSON节点对象  
  31.         JsonNode bindJsonNode = mapper.readValue(GENERIC_BINDING, JsonNode.class);//绑定JSON到JSON节点对象.  
  32.         //绑定JSON节点  
  33.         root.put("bindJsonNode",bindJsonNode);  
  34.         System.out.println(mapper.writeValueAsString(root));  
  35.     }  
private static final String TREE_MODEL_BINDING = "{"treekey1":"treevalue1","treekey2":"treevalue2","children":[{"childkey1":"childkey1"}]}";
        public void treeModelBinding() throws Exception{
                ObjectMapper mapper = new ObjectMapper();
                JsonNode rootNode = mapper.readTree(TREE_MODEL_BINDING);
                //path与get作用相同,但是当找不到该节点的时候,返回missing node而不是Null.
                String treekey2value = rootNode.path("treekey2").getTextValue();//
                System.out.println("treekey2value:" + treekey2value);
                JsonNode childrenNode = rootNode.path("children");
                String childkey1Value = childrenNode.get(0).path("childkey1").getTextValue();
                System.out.println("childkey1Value:"+childkey1Value);
                
                //创建根节点
                ObjectNode root = mapper.createObjectNode();
                //创建子节点1
                ObjectNode node1 = mapper.createObjectNode();
                node1.put("nodekey1",1);
                node1.put("nodekey2",2);
                //绑定子节点1
                root.put("child",node1);
                //数组节点
                ArrayNode arrayNode = mapper.createArrayNode();
                arrayNode.add(node1);
                arrayNode.add(1);
                //绑定数组节点
                root.put("arraynode", arrayNode);
                //JSON读到树节点
                JsonNode valueToTreeNode = mapper.valueToTree(TREE_MODEL_BINDING);
                //绑定JSON节点
                root.put("valuetotreenode",valueToTreeNode);
                //JSON绑定到JSON节点对象
                JsonNode bindJsonNode = mapper.readValue(GENERIC_BINDING, JsonNode.class);//绑定JSON到JSON节点对象.
                //绑定JSON节点
                root.put("bindJsonNode",bindJsonNode);
                System.out.println(mapper.writeValueAsString(root));
        }

3、Streaming API:最佳性能。

见官方文档例子。

 

参考资料:

1、http://wiki.fasterxml.com/JacksonInFiveMinutes Jackson官方教程示例

2、http://wiki.fasterxml.com/JacksonJavaDocs Jackson在线API文档

3、http://hjg1988.iteye.com/blog/561368 JSON工具性能比较:json-lib和jackson进行Java对象到json字符串序列化。

 


posted on 2022-10-04 01:29  bdy  阅读(184)  评论(0编辑  收藏  举报

导航