fastjson的循环引用和重复引用的问题排解

前言

项目中用json形式来存储一个集合对象,用fastjson发现多了一些东西:$ref,了解之后才发现是重复引用的问题,现在总结一下

重复引用问题代码

类定义:

 public static class Box{
        private int id;
        private String name;
        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }
    }

调试代码:

        Box oneBox = new Box();
        oneBox.setId(1);
        oneBox.setName("one");
        Box twoBox = new Box();
        twoBox.setId(2);
        twoBox.setName("two");

        Box thrBox = new Box();
        thrBox.setId(3);
        thrBox.setName("thr");

        List<Box> boxList = Lists.newArrayList();
        boxList.add(oneBox);
        boxList.add(oneBox);  // 此地方重复加入了oneBox 对象
        boxList.add(twoBox);
        boxList.add(thrBox);
        String strBoxList= JSON.toJSONString(boxList);
        System.out.println(strBoxList);

// 结果:
[{"id":1,"name":"one"},{"$ref":"$[0]"},{"id":2,"name":"two"},{"id":3,"name":"thr"}]

循环引用

代码

// 类定义
    public static class Tree{
        private int id;
        private String name;

        private Tree nextTree;
        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Tree getNextTree() {
            return nextTree;
        }

        public void setNextTree(Tree nextTree) {
            this.nextTree = nextTree;
        }
    }
   

调试代码:

 Tree oneTree = new Tree();
        oneTree.setId(1);
        oneTree.setName("one");

        Tree twoTree = new Tree();
        twoTree.setId(2);
        twoTree.setName("two");
        twoTree.setNextTree(oneTree);

        Tree thrTree = new Tree();
        thrTree.setId(3);
        thrTree.setName("thr");
        thrTree.setNextTree(oneTree);

        oneTree.setNextTree(twoTree);

        List<Tree> boxList = Lists.newArrayList();
        boxList.add(oneTree);
        boxList.add(twoTree);
        boxList.add(thrTree);
        String strBoxListTwo = JSON.toJSONString(boxList);
        System.out.println(strBoxListTwo);
// 运行结果:
[{"id":1,"name":"one","nextTree":{"id":2,"name":"two","nextTree":{"$ref":".."}}},{"$ref":"$[0].nextTree"},{"id":3,"name":"thr","nextTree":{"$ref":"$[0]"}}]

解决问题

  • 1、对数据进行转换,new 一个新对象,然后赋值。
  • 2、采用fastjson的特性,JSON.toJSONString(object, SerializerFeature.DisableCircularReferenceDetect);
    此方法有风险,引用检测是FastJson提供的一种避免运行时异常的优良机制,如果关闭它,会有很大可能导致循环引用时发生StackOverflowError异常。这也是FastJson默认开启引用检测的原因。
  • 3、循环引用应该是代码逻辑问题,大家尽可能的避免这类问题。

fastjson其他坑

  1. 在使用Set类型时,不要加范型参数,否则会出现类似com.alibaba.fastjson.JSONArray cannot be cast to java.util.Set这样的错误(目前请尽量避免使用Set作为参数类型吧)
    2、使用JSON形式的序列化技术时,所有通信传递的对象必须设置无参的默认构造函数
    3、当传递的对象属性中存在内部类时,请保证内部类为static的,不支持对象内部类
    4、fastjson传递的参数中不要和其他形式的json对象混用,如net.sf.json、org.json、gson等等,会出现不兼容
    5、fastjson默认根据get和set方法来生成json体中的属性键值对,所以同个属性的set方法不要重载,保证简单,负责会出现不确定的赋值后状态
    6、针对Bool类型的属性的getXXX和isXXX方法会存在冲突,具体以哪一个为准还不确定,所以请保证你的POJO对象只会存在一种

参考博客

解决fastjson内存对象重复/循环引用json错误 转

    原文作者:予亭
    原文地址: https://blog.csdn.net/randompeople/article/details/95382523
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞