视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
使用json-lib完成json的序列化和反序列化
2025-09-29 02:20:41 责编:小OO
文档
使用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;//部门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 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 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等方法相当有用。

    希望我今天的这些心得对大家有一些帮助。下载本文

显示全文
专题