使用json-lib完成json的序列化和反序列化2011-07-29 14:07:43分类:默认分类 | 标签:软件 java json.json的序列化和反序列化在现在的javaweb中特别是ajax中使用的比较频繁,现在本人就这种技术提出自己的使用心得。
我的pojo对象的结构是这样的部门表和员工表 1对多的关系部门对象public class Dept implements java.io.Serializable {private Integer depid;//部门IDprivate String depname;//部门名称private Set emps = new HashSet(0);//员工集合}员工对象public class Emp implements java.io.Serializable {private Integer empid;//员工idprivate 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=newClassPathXmlApplicationContext("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=newClassPathXmlApplicationContext("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=newClassPathXmlApplicationContext("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=newClassPathXmlApplicationContext("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-ddHH: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);}这种方案可以解决死循环问题和日期格式化的问题。