JSON

JSON的序列化和反序列化

json的序列化和反序列化在现在的javaweb中特别是ajax中使用的比较频繁,现在本人就这种技术提出自己的使用心得。

我的pojo对象的结构是这样的

部门表和员工表    1对多的关系

部门对象

Java代码   收藏代码
  1. <strong>public class Dept implements java.io.Serializable {  
  2. private Integer depid;//部门ID  
  3. private String depname;//部门名称  
  4. private Set emps = new HashSet(0);//员工集合  
  5. }</strong>  
 

员工对象

Java代码   收藏代码
  1. <strong>public class Emp implements java.io.Serializable {  
  2. private Integer empid;//员工id  
  3. private Dept dept;//部门  
  4. private String empname;//员工名称  
  5. private Date birthday;//生日  
  6. }</strong>  
 

1.json字符串序列化成对象

Java代码   收藏代码
  1. /** 
  2.  * 通过json转换成对象 
  3.  * @author 凤生禾予 
  4.  */  
  5. public void jsonToObject(){  
  6. Date d=new Date();  
  7. SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");  
  8. StringBuffer str=new StringBuffer();  
  9. // json字符串  
  10. str.append("{empid:1,dept:{depid:1,depname:'开发部'},empname:'张三',birthday:'"+sdf.format(d)+"'}");  
  11. // 使用JSONObject将json序列化对象  
  12. JSONObject obj=JSONObject.fromObject(str.toString());  
  13. // 将JOSNObject对象转换成pojo对象  
  14. Emp emp=(Emp) JSONObject.toBean(obj,Emp.class);  
  15. System.out.println(emp.getBirthday());  
  16. }  
 

这里需要注意的是json字符串的写法以{}表示一个对象,字符串必须加引号 

2json字符串序列化成集合

Java代码   收藏代码
  1. /** 
  2.  * 通过json转换成集合 
  3.  * @author 凤生禾予 
  4.  */  
  5. public void jsonToArray(){  
  6. Date d=new Date();  
  7. SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");  
  8. StringBuffer str=new StringBuffer();  
  9. //json字符串  
  10. str.append("[");  
  11. str.append("{empid:1,dept:{depid:1,depname:'开发部'},empname:'张三',birthday:'"+sdf.format(d)+"'}");  
  12. str.append(",");  
  13. str.append("{empid:2,dept:{depid:1,depname:'开发部'},empname:'李四',birthday:'"+sdf.format(d)+"'}");  
  14. str.append("]");  
  15. //将json转换成JSONArray对象  
  16. JSONArray arr=JSONArray.fromObject(str.toString());  
  17. //使用JSONArray转换成集合  
  18. List<Emp> list=JSONArray.toList(arr,Emp.class);  
  19. for (Emp emp : list) {  
  20. System.out.println(emp.getEmpname());  
  21. System.out.println(emp.getBirthday());  
  22. System.out.println(emp.getDept().getDepname());  
  23. }  
  24. }  
 

这里需要注意的是json的数组用法为[]

3.对象反序列化成json

Java代码   收藏代码
  1.  /** 
  2.   * 通过对象转换成json 
  3.   * @author 凤生禾予 
  4.   */  
  5. public void objectToJson(){  
  6. ClassPathXmlApplicationContext xa=new ClassPathXmlApplicationContext("applicationContext.xml");  
  7. EmpDAO dao=(EmpDAO) xa.getBean("EmpDAO");  
  8. //查找对象  
  9. Emp emp=dao.findById(27);  
  10. String s=JSONObject.fromObject(emp).toString();  
  11. System.out.println(s);  
  12. }  
 

这里会有2个问题

1.pojo中对象存在有死循环问题,部门类中有员工对象的集合,员工类中有部门的对象,json-lib反序列化中会进行双向转换,从而形成死循环,会报一个json-lib的经典异常:

Java代码   收藏代码
  1. Exception in thread "main" net.sf.json.JSONException: There is a cycle in the hierarchy!  
 

2.日期类型转换

json-lib转换出来的日期类型格式

Js代码   收藏代码
  1. "birthday":{"date":1,"day":0,"hours":0,"minutes":0,"month":7,"nanos":0,"seconds":0,"time":1280592000000,"timezoneOffset":-480,"year":110}  
 

那么我们如果想要yyyy-MM-dd HH:mm:ss 这种格式的怎么办呢?

那么解决方案有3

都必须使用jsonConfig对象进行处理

(1)使用jsonConfigsetExcludes的方法进行过滤,将所需要过滤的字段名传入setExcludes方法

Java代码   收藏代码
  1. <strong>public void objectToJson(){  
  2. ClassPathXmlApplicationContext xa=new ClassPathXmlApplicationContext("applicationContext.xml");  
  3. EmpDAO dao=(EmpDAO) xa.getBean("EmpDAO");  
  4. //查找对象  
  5. Emp emp=dao.findById(27);  
  6. //创建jsonConfig对象  
  7. JsonConfig config=new JsonConfig();  
  8. //设置过滤字段  
  9. config.setExcludes(new String[]{"dept"});  
  10. String s=JSONObject.fromObject(emp,config).toString();  
  11. System.out.println(s);  
  12. }</strong>  
 

2)使用jsonConfigsetJsonPropertyFilter进行属性过滤,过滤器中返回true表示过滤该字段,返回false表示可以转换该字段

Java代码   收藏代码
  1. <strong>public void objectToJson(){  
  2. ClassPathXmlApplicationContext xa=new ClassPathXmlApplicationContext("applicationContext.xml");  
  3. EmpDAO dao=(EmpDAO) xa.getBean("EmpDAO");  
  4. //查找对象  
  5. Emp emp=dao.findById(27);  
  6. //创建jsonConfig对象  
  7. JsonConfig config=new JsonConfig();  
  8. //设置过滤字段  
  9. config.setJsonPropertyFilter(new PropertyFilter() {  
  10. public boolean apply(Object arg0, String arg1, Object arg2) {  
  11. if("dept".equals(arg1)){  
  12. return true;  
  13. }  
  14. return false;  
  15. }  
  16. });  
  17. String s=JSONObject.fromObject(emp,config).toString();  
  18. System.out.println(s);  
  19. }</strong>  
 

上述两种解决方案可以解决部分问题,但是json-lib使用代理进行反射,所以如果想要部门表的信息,而去过滤部门表的员工对象,这样还是解决不了。这样可以使用更简单有效的方案

3)使用jsonConfigsetCycleDetectionStrategy()方法进行忽略死循环

使用jsonConfigregisterJsonValueProcessor()进行属性转换设置

  /**

Java代码   收藏代码
  1. * 通过对象转换成json  
  2. @author 凤生禾予  
  3. */  
  4. public void objectToJson(){  
  5. ClassPathXmlApplicationContext xa=new ClassPathXmlApplicationContext("applicationContext.xml");  
  6. EmpDAO dao=(EmpDAO) xa.getBean("EmpDAO");  
  7. //查找对象  
  8. Emp emp=dao.findById(27);  
  9. //创建jsonConfig对象  
  10. JsonConfig config=new JsonConfig();  
  11. //设置循环策略为忽略    解决json最头疼的问题 死循环  
  12. config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);  
  13. //设置 json转换的处理器  用来处理日期类型  
  14. //凡是反序列化Date类型的对象,都会经过该处理器进行处理  
  15. config.registerJsonValueProcessor(Date.classnew JsonValueProcessor() {  
  16. //参数1 :属性名   参数2:json对象的值   参数3:jsonConfig对象  
  17. public Object processObjectValue(String arg0, Object arg1, JsonConfig arg2) {  
  18. SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  19. Date d=(Date) arg1;  
  20. return sdf.format(d);  
  21. }  
  22. public Object processArrayValue(Object arg0, JsonConfig arg1) {  
  23. return null;  
  24. }  
  25. });  
  26. String s=JSONObject.fromObject(emp,config).toString();  
  27. System.out.println(s);  
  28. }  
 

这种方案可以解决死循环问题和日期格式化的问题。

结果:

Js代码   收藏代码
  1. {"birthday":"2010-08-01 00:00:00","dept":{"depid":1,"depname":"开发部","emps":[{"birthday":"2009-08-01 00:00:00","dept":null,"empid":30,"empname":"田七"},null]},"empid":27,"empname":"王五"}  
 

3.集合反序列化成json

Java代码   收藏代码
  1. /** 
  2. * 通过集合转换成json 
  3. * @author  凤生禾予 
  4. */  
  5. public void arrayToJson(){  
  6. ClassPathXmlApplicationContext xa=new ClassPathXmlApplicationContext("applicationContext.xml");  
  7. EmpDAO dao=(EmpDAO) xa.getBean("EmpDAO");  
  8. List<Emp> emps=dao.findAll();  
  9. JsonConfig config=new JsonConfig();  
  10. config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);  
  11. config.registerJsonValueProcessor(Date.classnew JsonValueProcessor() {  
  12. @Override  
  13. public Object processObjectValue(String arg0, Object arg1, JsonConfig arg2) {  
  14. // TODO Auto-generated method stub  
  15. SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
  16. Date d=(Date) arg1;  
  17. return sdf.format(d);  
  18. }  
  19. @Override  
  20. public Object processArrayValue(Object arg0, JsonConfig arg1) {  
  21. // TODO Auto-generated method stub  
  22. return null;  
  23. }  
  24. });  
  25. String s=JSONArray.fromObject(emps,config).toString();  
  26. System.out.println(s);  
  27. }  
 

 这个和上面没有太多区别。

总结:使用json-lib进行对象的序列化和反序列化的文档比较少,在工作中进行及时总结经验是一个比较好的方式。

  json-lib对象的序列化比较简单,重要的是使用JSONObjectJSONArray两个对象,这两个对象进行序列化pojo对象之前,必须将json转换成对应的JSONObjectJSONArray对象。

 json-lib对象的反序列化相对复杂些,因为反序列时json-lib通过代理对对象进行反射操作将对象生成json,特别在Hibernate中容易产生死循环操作,而且对一些日期和其他的复杂对象的转换可能和我们的预期不一致,所以一定要对jsonConfig对象进行详细研究,其中的

setExcludes,

setJsonPropertyFilter,

setCycleDetectionStrategy,

registerJsonValueProcessor等方法相当有用。

希望我今天的这些心得对大家有一些帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值