一、基本介绍
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) |
Integer, Long 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测试用例运行的,所以还得添加junit的jar包。
版本是junit-4.2.8
2.测试的项目
目前要进行hibernate的懒加载等其它功能,我直接使用joffice项目的工程,避免要配置hibernate等测试环境。
Department.java
/** * @description 部门管理 * @class Department * @author 宏天软件 * @company www.jee-soft.cn * @createtime 2011-1-18AM * */ public class Department extends BaseModel { public final static long serialVersionUID = 1L; /**集团*/ public final static Short ORG_TYPE_GROUP=0; /**公司*/ public final static Short ORG_TYPE_COMPANY=1; /**部门*/ public final static Short ORG_TYPE_DEPARTMENT=2; protected Long depId; protected String depName; protected String depDesc; protected Integer depLevel; protected Long parentId; protected String path; protected Short orgType; protected Long creatorId; protected java.util.Date createtime; protected Long updateId; protected java.util.Date updatetime; protected Integer sn; protected com.htsoft.oa.model.system.Demension demension; protected Set appUsers = new java.util.HashSet(); protected Set userOrgs = new java.util.HashSet(); protected String chargeIds; protected String chargeNames; //====get和set 省略 }Demension.java
/** * @description 维度管理 * @class Department * @author 宏天软件 * @company www.jee-soft.cn * @createtime 2011-1-18AM */ public class Demension extends com.htsoft.core.model.BaseModel { /** * 行政维度的id */ public final static Long ADMIN_DEMENSION_ID=1l; protected Long demId; protected String demName; protected String demDesc; protected Long demType; protected java.util.Set organizations = newjava.util.HashSet(); //====get和set 省略 }
三、一些常用的示例三、一些常用的示例
具体的帮助类请参考 ——》
1.Object转Json
Object可以是String,Integer,Long,List ,pojo(实体) 等对象
通过调用方法如下:
输出结果:
2.Json转Object
测试类:
输出结果:
3.日期格式设置
你看上面的例子 object转Json日期输入的是时间戳(数字)的格式,那我们需要把它转换成我们需要的日期格式比如: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".
当然也可以自定义输出格式:
2)注解方式
可以支持序列化(@JsonSerialize(using=CustomDateTimeSerializer.class))
和反序列化(@JsonDeserialize(using=CustomDateTimeDeserializer.class))
然后在你的POJO上找到日期的属性上加上:
4.解决hibernate延时加载设置
因为jsonplugin用的是java的内审机制.hibernate会给被管理的pojo加入一个 hibernateLazyInitializer属性,jsonplugin会把hibernateLazyInitializer也拿出来操作,并读取里面一个不能被反射操作的属性就产生了这个异常.
1)不过我用的是jackson来转json,所以想到了用annotation来排除hibernateLazyInitializer这个属性
在你的pojo类声明加上
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
(这里是一个简单的例子,双联链表,引用都在同一类)
public class Node { public String name; // simple property // reference with default name @JsonManagedReference public SimpleTreeNode child; // forward reference, serialized @JsonBackReference public Node parent; // backward reference, not serialized public SimpleTreeNode() { this(null); } 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:
public class NodeList { @JsonManagedReference public List<NodeForList> nodes; } public class NodeForList { public String name; @JsonBackReference public NodeList parent; public NodeForList() { this(null); } public NodeForList(String n) { name = n; } }
and it is possible to use multiple references, by specifying distinct names:(通过指定不同的名称,可以使用多个引用:)
public class FullTreeNode { public String name; // parent-child links @JsonBackReference("parent") public FullTreeNode parent; @JsonManagedReference("parent") public FullTreeNode firstChild; // sibling-links @JsonManagedReference("sibling") public FullTreeNode next; @JsonBackReference("sibling") protected FullTreeNode prev; public FullTreeNode() { this(null); } public FullTreeNode(String name) { this.name = name; } }
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,并且可以自动侦测getter,setter,构造方法,以便生成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'的被序列总是在其他属性之前)
可以用来指示明确(但可以是部分的)序列化属性的顺序。
⑤ @ JsonFilter(class):表示这BeanPropertyFilter使用注解的类的属性的动态过滤。此外,一个有定义PropertyFilterProvider ObjectWriter(要么在使用ObjectMapper.filteredWriter(),或ObjectWriter.withFilters()),当序列化用于动态解决实际使用中的过滤器。
⑥ @ JsonIgnoreType(class):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.
指示,注释类型的物业从来没有被序列化,忽略代理类型或生成的类所使用的元数据存取,这是有用的。
还有些注解,那你就要参考官方的文档了,就看官方文档: