Jackson 框架 用例详解

广州宏天软件公司论坛

zxh - 2012-7-26 17:30:29

Jackson 框架 用例详解

      目录

一、         基本介绍.............................2

二、         准备工作............... ............2

三、         一些常用的示例............... 4

    1.ObjectJson..............................5

    2.JsonObject..............................6

    3.日期格式设置............................6

      1)普通的方式..............................6

      2)注解方式..................................7

    4.解决hibernate延时加载设置.... 8

    5.设置循环策略............................8

       1)父子关系引用........................ 9

        2)@JsonIgnore注解....................9

     6.属性过滤................................. 10

          1)使用@JsonFilter注解.......... 10

           2)添加混合式注解...............10

7.其它annotation(注解)..............10

一、基本介绍

Jackson的功能好处就不介绍

具体见:http://bbs.jee-soft.cn:8086/showtopic-155.aspx

官方介绍:http://www.cowtowncoder.com/blog/archives/2010/11/entry_434.html

Concrete Java types that Jackson will use for simple data binding are:

JSON Type

Java Type

object

LinkedHashMap<String,Object>

array

ArrayList<Object>

string

String

number (no fraction)

IntegerLong or BigInteger (smallest applicable)

number (fraction)

Double (configurable to use BigDecimal)

true|false

Boolean

null

null

二、准备工作

1、下载依赖库jar

Jackson maven 目前有2.0暂时使用1.9.8比较稳定


<dependency>


<groupId>org.codehaus.jackson</groupId>


<artifactId>jackson-core-asl</artifactId>


<version>1.9.8</version>


<type>jar</type>


<scope>compile</scope>


</dependency>


<dependency>


<groupId>org.codehaus.jackson</groupId>


<artifactId>jackson-core-lgpl</artifactId>


<version>1.9.8</version>


<type>jar</type>


<scope>compile</scope>


</dependency>


官方示例:http://wiki.fasterxml.com/JacksonInFiveMinutes

因为下面的程序是用junit测试用例运行的,所以还得添加junitjar包。

版本是junit-4.2.8

2.测试的项目

目前要进行hibernate的懒加载等其它功能,我直接使用joffice项目的工程,避免要配置hibernate等测试环境。

Department.java

  1. /**
  2. * @description 部门管理
  3. * @class Department
  4. * @author 宏天软件
  5. * @company www.jee-soft.cn
  6. * @createtime 2011-1-18AM

  7. */
  8. public class Department extends BaseModel {

  9. public final static long serialVersionUID = 1L;

  10. /**集团*/
  11. public final static Short ORG_TYPE_GROUP=0;

  12. /**公司*/
  13. public final static Short ORG_TYPE_COMPANY=1;

  14. /**部门*/
  15. public final static Short ORG_TYPE_DEPARTMENT=2;

  16. protected Long depId;

  17. protected String depName;

  18. protected String depDesc;

  19. protected Integer depLevel;

  20. protected Long parentId;

  21. protected String path;

  22. protected Short orgType;

  23. protected Long creatorId;

  24. protected java.util.Date createtime;

  25. protected Long updateId;

  26. protected java.util.Date updatetime;

  27. protected Integer sn;

  28. protected com.htsoft.oa.model.system.Demension demension;

  29. protected Set appUsers = new java.util.HashSet();

  30. protected Set userOrgs = new java.util.HashSet();

  31. protected String chargeIds;

  32. protected String chargeNames;

  33. //====get和set 省略
  34. }
复制代码





Demension.java

  1. /**
  2. * @description 维度管理
  3. * @class Department
  4. * @author 宏天软件
  5. * @company www.jee-soft.cn
  6. * @createtime 2011-1-18AM
  7. */
  8. public class Demension extends com.htsoft.core.model.BaseModel {

  9. /**
  10. * 行政维度的id
  11. */
  12. public final static Long ADMIN_DEMENSION_ID=1l;

  13. protected Long demId;

  14. protected String demName;

  15. protected String demDesc;

  16. protected Long demType;

  17. protected java.util.Set organizations = newjava.util.HashSet();

  18. //====get和set 省略
  19. }
复制代码



三、一些常用的示例

具体的帮助类请参考 ——》

jackson.rar (, 下载次数:75)

1.ObjectJson


68

Object可以是StringIntegerLongList ,pojo(实体等对象

         通过调用方法如下:

       
69

  

输出结果:

  1. {"version":null,"orgId":null,"orgPath":null,"depId":1,"depName":"宏天软件","depDesc":"宏天软件","depLevel":1,"parentId":0,"path":"0.1.","orgType":1,"creatorId":1,"createtime":1314547200000,"updateId":1,"updatetime":"1314547200000","sn":null,"chargeIds":"","chargeNames":"","demension":{"version":null,"orgId":null,"orgPath":null,"demId":1,"demName":"行政维度","demDesc":"行政维度","demType":1,"organizations":[]}}
复制代码


2.JsonObject


70

测试类:


71

输出结果:

  1. 宏天软件
  2. Mon Aug 29 08:00:00 CST 2011
  3. 行政维度
复制代码



3.日期格式设置

你看上面的例子 objectJson日期输入的是时间戳(数字)的格式,那我们需要把它转换成我们需要的日期格式比如:yyyy-MM-dd HH:mm:ss 2种方式解决这个问题:

1)普通的方式

默认是转成timestamps形式的,通过下面方式可以取消timestamps。

objectMapper.configure(Feature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT,false);


这样将使时间生成使用所谓的使用 [ISO-8601 ]-compliant notation, 输出类似如下格式的时间: "1970-01-01T00:00:00.000+0000".

当然也可以自定义输出格式:


72


73

2)注解方式
可以支持序列化@JsonSerialize(using=CustomDateTimeSerializer.class)
和反序列化(@JsonDeserialize(using=CustomDateTimeDeserializer.class)



74

75

然后在你的POJO上找到日期的属性上加上:


76

4.解决hibernate延时加载设置

因为jsonplugin用的是java的内审机制.hibernate会给被管理的pojo加入一个 hibernateLazyInitializer属性,jsonplugin会把hibernateLazyInitializer也拿出来操作,并读取里面一个不能被反射操作的属性就产生了这个异常.   
1)不过我用的是jackson来转json,所以想到了用annotation来排除hibernateLazyInitializer这个属性

在你的pojo类声明加上


77

2)采用别人写的相关插件 我用是hibernate3

import com.fasterxml.jackson.datatype.hibernate3.Hibernate3Module;


/**
* 带是否懒加载 的构造方法
* @param forceLazyLoading 是否懒加载   true为懒加载,否则false
*/
public JacksonMapper(boolean forceLazyLoading){
Hibernate3Module mod = new Hibernate3Module();
     mod.configure(Hibernate3Module.Feature.FORCE_LAZY_LOADING, forceLazyLoading);
     registerModule(mod);
}


5.设置循环策略 :解决json最头疼的问题死循环  

能够干净地处理循环类型的某些子集,成为父/子链接。 这些都是互相紧密耦合的引用,其中两个对象以层次结构的方式交叉引用,如父/子树节点的关联,或更常见的,ORM采用的表间连接(join)的描述。

对引用问题(或更普遍的,循环引用),JSON没有处理它们的自然方法。,不像Java对象,没有标识信息可用。
  常用的解决方法是只标记一个被忽略的引用(Jackson可通过使用
@ JsonIgnore解实现),但其缺点是反序列化时会丢失实际的耦合目标。
Jackson 有简单的基于注解的解决该问题的方案:两个引用需要一个注解(对连接作@JsonManagedReference 注解,对返回连接作@JsonBackReference注解),并在此基础,Jackson知道要省略反向引用的序列化,但反序列化对象时要恢复它。此方式适用于典型的ORM用例。
1)父子关系引用

直接输出肯定是报循环错误,Jackson 提供了两个注解

@JsonManagedReference @JsonBackReference


@JsonManagedReference

protected com.htsoft.oa.model.system.Demension demension;


@JsonBackReference

protected Set appUsers = new java.util.HashSet();




参考这:http://wiki.fasterxml.com/JacksonFeatureBiDirReferences

把官网的例子拿下来分析:New annotations
Annotations are: 
@JsonManagedReference is the "forward" part of reference: one that gets serialized normally, and handling of which triggers back-linkage for the other reference 
Annotated property can be a bean, array, Collection (List, Set) or Map type, and it must be a bean property (handled by a property of type serialized using BeanSerializer 
@JsonBackReference is the "back" part of reference: it will be omitted from serialization, and re-constructed during deserialization of forward reference. 
翻译器翻译:(
新的注解
注解是:
@ JsonManagedReference是“前进”的部分关联:一,通常被序列化,并处理其中触发后面的其他参考联动
注释的属性可以是一个Bean,数组,集合(List,Set)或Map类型,它必须是一个bean的属性(使用的BeanSerializer序列类型的属性处理
@ JsonBackReference是“反向的关联:从序列,它会被省略,向前引用的反序列化过程中重新构建。

Example

Here is a simple example of a double-linked linked list, where references are both in same class 

(这里是一个简单的例子,双联链表,引用都在同一类)

  1. public class Node
  2. {
  3.     public String name; // simple property

  4.     // reference with default name        
  5.     @JsonManagedReference public SimpleTreeNode child; // forward reference, serialized
  6.     @JsonBackReference public Node parent; // backward reference, not serialized

  7.     public SimpleTreeNode() { this(null); }
  8.     public SimpleTreeNode(String n) { name = n; }
复制代码

Linkage also works for structured types (arrays, Collections, Maps), as long as only forward reference is of such type. For example: 

  1. public class NodeList
  2. {
  3.     @JsonManagedReference
  4.     public List&lt;NodeForList&gt; nodes;
  5. }

  6. public class NodeForList
  7. {
  8.     public String name;
  9.       
  10.     @JsonBackReference public NodeList parent;

  11.     public NodeForList() { this(null); }
  12.     public NodeForList(String n) { name = n; }
  13. }
复制代码

and it is possible to use multiple references, by specifying distinct names:(通过指定不同的名称,可以使用多个引用:)

  1. public class FullTreeNode
  2. {
  3.     public String name;

  4.     // parent-child links
  5.     @JsonBackReference("parent")
  6.     public FullTreeNode parent;
  7.     @JsonManagedReference("parent")
  8.     public FullTreeNode firstChild;

  9.     // sibling-links
  10.     @JsonManagedReference("sibling")
  11.     public FullTreeNode next;
  12.     @JsonBackReference("sibling")
  13.     protected FullTreeNode prev;
  14.         
  15.     public FullTreeNode() { this(null); }
  16.     public FullTreeNode(String name) {
  17.         this.name = name;
  18.     }
  19. }
复制代码

One final note: if using getter and setter methods instead of fields, you will may to add reference annotations on both methods (you will always need them in setters which are used for deserialization; getters for forward references are handled correctly without annotations, but getters for serializing back links do need to be annotated). 



2)@JsonIgnore注解

只说父子引用关系的。父子两边都加@JsonIgnore打印字符串为:

{"name":"chris","createDate":"2012-04-18"},{"title":"title"}


单向User加该注解

@JsonIgnore

public Set<Article> getArticles() {

   return articles;

}


打印结果为:

{"name":"chris","createDate":"2012-04-18"}

{"title":"title","user":{"name":"chris","createDate":"2012-04-18"}}


单向Article 加该注解


@JsonIgnore

public User getUser() {

   return user;

}


打印结果:

{"name":"chris","createDate":"2012-04-18","articles":[{"title":"title"}]}

{"title":"title"}


6.属性过滤

@JsonIgnoreProperties

这个加在类级别上, 用法很简单@JsonIgnoreProperties({"property1", "property2"})

动态过滤属性,这个比较麻烦。

有两种方法:

1)使用@JsonFilter注解

使用方法为先给ObjectMapper添加一个filter,然后还要在需要过滤的类上加@JsonFilter("filterName")
注解

比如说要过滤User 上的name属性,先

Jacksons.me().filter("myFilter""name").readAsString(user)具体看Jacksons代码。并在User类上加@JsonFilter("myFilter")

有点不爽的是如果用另外一个没有添加该filter的ObjectMapper解析的话会报错。

如果这个User类已经添加了@JsonFilter("myFilter")注解,但在另外一个地方又要解析它并不想过滤name 属性,那只能是Jacksons.me().filter("myFilter"""),然后在读出来。

2)添加混合式注解(暂时这么翻译)

定义一个接口或类先, 在该类上添加@JsonIgnoreProperties("name"), 然后在ObjectMapper的配置项上添加混入注解

输出为:

String mixInUser = Jacksons.me().addMixInAnnotations(User.class, MixInUser.class).readAsString(user);

System.out.println(mixInUser);

可以参考:http://www.cowtowncoder.com/blog/archives/2009/08/entry_305.html

7.其它annotation(注解)

① @JsonAutoDetect (class)这是作用于类的annotation,主要用于指明该类使用annotation,并且可以自动侦测gettersetter,构造方法,以便生成json对象

 @JsonIgnore (method/field):作用于方法或字段,用来表明,当生成json的时候忽略有该annotation的方法或字段

③ @JsonIgnoreProperties (value = { "hibernateLazyInitializer" ,  "password" }) ,主要用于过滤掉一些不需要的属性

④ @JsonPropertyOrder({ "id", "name" }) // ensure that 'id' and 'name' are always serialized before other properties(确保'id''name'的被序列总是在其他属性之前)

可以用来指示明确(但可以是部分的)序列化属性的顺序。

 @ JsonFilterclass):表示这BeanPropertyFilter使用注解的类的属性的动态过滤。此外,一个有定义PropertyFilterProvider ObjectWriter(要么在使用ObjectMapper.filteredWriter(),或ObjectWriter.withFilters()),当序列化用于动态解决实际使用中的过滤器。

 @ JsonIgnoreTypeclass):indicates that properties with annotated type are never to be serialized; this is useful for ignoring metadata accessors used by proxy types or generated classes.

指示,注释类型的物业从来没有被序列化,忽略代理类型或生成的类所使用的元数据存取,这是有用的。

还有些注解,那你就要参考官方的文档了,就看官方文档:

http://wiki.fasterxml.com/JacksonAnnotations

wwz - 2013-1-10 9:03:40
好东西而且活力四射...比古老的jsonlib确实好太多.
1
查看完整版本: Jackson 框架 用例详解

没有更多推荐了,返回首页