使用json-lib完成json的序列化和反序列化

使用json-lib完成json的序列化和反序列化  


json的序列化和反序列化在現在的javaweb中特別是ajax中使用的比較頻繁,現在本人就這種技術提出自己的使用心得。

我的pojo對象的結構是這樣的
部門表和員工表    1對多的關係
部門對象
public class Dept implements java.io.Serializable {
private Integer depid;//部門ID
private String depname;//部門名稱
private Set emps = new HashSet(0);//員工集合
}
員工對象
public class Emp implements java.io.Serializable {
private Integer empid;//員工id
private Dept dept;//部門
private String empname;//員工名稱
private Date birthday;//生日
}



1.json字符串序列化成對象
/**
* 通過json轉換成對象
* @author 株洲健坤北大青鳥  周鋼
*/
public void jsonToObject(){
Date d=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
StringBuffer str=new StringBuffer();
//json字符串
str.append("{empid:1,dept:{depid:1,depname:'開發部'},empname:'張三',birthday:'"+sdf.format(d)+"'}");
//使用JSONObject將json序列化對象
JSONObject obj=JSONObject.fromObject(str.toString());
//將JOSNObject對象轉換成pojo對象
Emp emp=(Emp) JSONObject.toBean(obj,Emp.class);
System.out.println(emp.getBirthday());
}
 這裏需要注意的是json字符串的寫法以{}表示一個對象,字符串必須加引號


2json字符串序列化成集合
/**
* 通過json轉換成集合
* @author 株洲健坤北大青鳥  周鋼
*/
public void jsonToArray(){
Date d=new Date();
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd");
StringBuffer str=new StringBuffer();
//json字符串
str.append("[");
str.append("{empid:1,dept:{depid:1,depname:'開發部'},empname:'張三',birthday:'"+sdf.format(d)+"'}");
str.append(",");
str.append("{empid:2,dept:{depid:1,depname:'開發部'},empname:'李四',birthday:'"+sdf.format(d)+"'}");
str.append("]");
//將json轉換成JSONArray對象
JSONArray arr=JSONArray.fromObject(str.toString());
//使用JSONArray轉換成集合
List<Emp> list=JSONArray.toList(arr,Emp.class);
for (Emp emp : list) {
System.out.println(emp.getEmpname());
System.out.println(emp.getBirthday());
System.out.println(emp.getDept().getDepname());
}
}
這裏需要注意的是json的數組用法爲[]


3.對象反序列化成json
 /**
 * 通過對象轉換成json
 * @author 株洲健坤北大青鳥  周鋼
 */
public void objectToJson(){
ClassPathXmlApplicationContext xa=new ClassPathXmlApplicationContext("applicationContext.xml");
EmpDAO dao=(EmpDAO) xa.getBean("EmpDAO");
//查找對象
Emp emp=dao.findById(27);
String s=JSONObject.fromObject(emp).toString();
System.out.println(s);
}
這裏會有2個問題
1.pojo中對象存在有死循環問題,部門類中有員工對象的集合,員工類中有部門的對象,json-lib反序列化中會進行雙向轉換,從而形成死循環,會報一個json-lib的經典異常:
Exception in thread "main" net.sf.json.JSONException: There is a cycle in the hierarchy!

2.日期類型轉換
json-lib轉換出來的日期類型格式
"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)使用jsonConfig的setExcludes的方法進行過濾,將所需要過濾的字段名傳入setExcludes方法
public void objectToJson(){
ClassPathXmlApplicationContext xa=new ClassPathXmlApplicationContext("applicationContext.xml");
EmpDAO dao=(EmpDAO) xa.getBean("EmpDAO");
//查找對象
Emp emp=dao.findById(27);
//創建jsonConfig對象
JsonConfig config=new JsonConfig();
//設置過濾字段
config.setExcludes(new String[]{"dept"});
String s=JSONObject.fromObject(emp,config).toString();
System.out.println(s);
}


(2)使用jsonConfig的setJsonPropertyFilter進行屬性過濾,過濾器中返回true表示過濾該字段,返回false表示可以轉換該字段
public void objectToJson(){ClassPathXmlApplicationContext xa=new ClassPathXmlApplicationContext("applicationContext.xml");EmpDAO dao=(EmpDAO) xa.getBean("EmpDAO");//查找對象Emp emp=dao.findById(27);//創建jsonConfig對象JsonConfig config=new JsonConfig();//設置過濾字段config.setJsonPropertyFilter(new PropertyFilter() {public boolean apply(Object arg0, String arg1, Object arg2) {if("dept".equals(arg1)){return true;}return false;}});String s=JSONObject.fromObject(emp,config).toString();System.out.println(s);}
上述兩種解決方案可以解決部分問題,但是json-lib使用代理進行反射,所以如果想要部門表的信息,而去過濾部門表的員工對象,這樣還是解決不了。這樣可以使用更簡單有效的方案

(3)使用jsonConfig的setCycleDetectionStrategy()方法進行忽略死循環
使用jsonConfig的registerJsonValueProcessor()進行屬性轉換設置
        /**
* 通過對象轉換成json
* @author 株洲健坤北大青鳥  周鋼
*/
public void objectToJson(){
ClassPathXmlApplicationContext xa=new ClassPathXmlApplicationContext("applicationContext.xml");
EmpDAO dao=(EmpDAO) xa.getBean("EmpDAO");
//查找對象
Emp emp=dao.findById(27);
//創建jsonConfig對象
JsonConfig config=new JsonConfig();
//設置循環策略爲忽略    解決json最頭疼的問題 死循環
config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
//設置 json轉換的處理器  用來處理日期類型
//凡是反序列化Date類型的對象,都會經過該處理器進行處理
config.registerJsonValueProcessor(Date.class, new JsonValueProcessor() {
//參數1 :屬性名   參數2:json對象的值   參數3:jsonConfig對象
public Object processObjectValue(String arg0, Object arg1, JsonConfig arg2) {
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d=(Date) arg1;
return sdf.format(d);
}
public Object processArrayValue(Object arg0, JsonConfig arg1) {
return null;
}
});
String s=JSONObject.fromObject(emp,config).toString();
System.out.println(s);
}
這種方案可以解決死循環問題和日期格式化的問題。
結果:
{"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
/**
* 通過集合轉換成json
* @author 株洲健坤北大青鳥  周鋼
*/
public void arrayToJson(){
ClassPathXmlApplicationContext xa=new ClassPathXmlApplicationContext("applicationContext.xml");
EmpDAO dao=(EmpDAO) xa.getBean("EmpDAO");
List<Emp> emps=dao.findAll();
JsonConfig config=new JsonConfig();
config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
config.registerJsonValueProcessor(Date.class, new JsonValueProcessor() {
@Override
public Object processObjectValue(String arg0, Object arg1, JsonConfig arg2) {
// TODO Auto-generated method stub
SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d=(Date) arg1;
return sdf.format(d);
}
@Override
public Object processArrayValue(Object arg0, JsonConfig arg1) {
// TODO Auto-generated method stub
return null;
}
});
String s=JSONArray.fromObject(emps,config).toString();
System.out.println(s);
}

 這個和上面沒有太多區別。


總結:使用json-lib進行對象的序列化和反序列化的文檔比較少,在工作中進行及時總結經驗是一個比較好的方式。
  json-lib對象的序列化比較簡單,重要的是使用JSONObject和JSONArray兩個對象,這兩個對象進行序列化pojo對象之前,必須將json轉換成對應的JSONObject和JSONArray對象。
 json-lib對象的反序列化相對複雜些,因爲反序列時json-lib通過代理對對象進行反射操作將對象生成json,特別在Hibernate中容易產生死循環操作,而且對一些日期和其他的複雜對象的轉換可能和我們的預期不一致,所以一定要對jsonConfig對象進行詳細研究,其中的setExcludes,setJsonPropertyFilter,setCycleDetectionStrategy,registerJsonValueProcessor等方法相當有用。
希望我今天的這些心得對大家有一些幫助。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章