JSON |
您所在的位置:网站首页 › servlet的流程 › JSON |
JSON的序列化和反序列化 json的序列化和反序列化在现在的javaweb中特别是ajax中使用的比较频繁,现在本人就这种技术提出自己的使用心得。 我的pojo对象的结构是这样的 部门表和员工表 1对多的关系 部门对象 Java代码 public class Dept implements java.io.Serializable { private Integer depid;//部门ID private String depname;//部门名称 private Set emps = new HashSet(0);//员工集合 }员工对象 Java代码 public class Emp implements java.io.Serializable { private Integer empid;//员工id private Dept dept;//部门 private String empname;//员工名称 private Date birthday;//生日 }1.json字符串序列化成对象 Java代码 /** * 通过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字符串序列化成集合 Java代码 /** * 通过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 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 Java代码 /** * 通过对象转换成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的经典异常: Java代码 Exception in thread "main" net.sf.json.JSONException: There is a cycle in the hierarchy!2.日期类型转换 json-lib转换出来的日期类型格式 Js代码 "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方法 Java代码 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表示可以转换该字段 Java代码 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()进行属性转换设置 /** Java代码 * 通过对象转换成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); }这种方案可以解决死循环问题和日期格式化的问题。 结果: Js代码 {"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代码 /** * 通过集合转换成json * @author 凤生禾予 */ public void arrayToJson(){ ClassPathXmlApplicationContext xa=new ClassPathXmlApplicationContext("applicationContext.xml"); EmpDAO dao=(EmpDAO) xa.getBean("EmpDAO"); List 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等方法相当有用。 希望我今天的这些心得对大家有一些帮助。 Json JSON JSON JSON json JSON JSON json Json json JSON json json JSON json JSON JSON json framework的res资源文件编译 全局 result (global-results) 的使用 八十九、基础框架(四十七)归档-利用 归档器 复制 物件 web.xml文件中配置(servlet,spring ,filter,listen)的加载顺序 九十、创建 一个简单的iOS应用程序 JSON db2常见问题及解决办法 我努力的爱你、你的心为什么还是没有被我融化呢? 让Qt得知来自硬件的中断 Eclipse插件安装 iOS App 中 OAuth 授权的实现方式 SLURM and OpenMPI mysql数据库修改数据库编码,字段编码与表编码 九十一、iOS应用程序开发架构 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |