1. 案例代码
1.1 案例一
多个元素持有同一个引用时。
案例代码:
public class TestFastJson {
    public static void main(String[] args) {
        ceshi();
    }
    public static void ceshi(){
        List<User> list = new ArrayList<>();
        //注意:此处的对象为同一个
        User user = new User();
        for (int i = 0; i <3 ; i++) {
            user.setName("李白");
            user.setAge("20");
            list.add(user);
        }
        String string = JSON.toJSONString(list);
        System.out.println(string);
    }
    @Data
    public static class User {
        private String name;
        private String age;
    }
}
响应结果:
[{"age":"20","name":"李白"},{"$ref":"$[0]"},{"$ref":"$[0]"}]
1.2 案例二
多个元素内部持有同一个引用时。
public class TestFastJson {
    public static void main(String[] args) {
        test2();
    }
    public static void test2() {
        List<UserPo> userPos = new ArrayList<>();
        //注意:此处的引用是一个
        List<Order> o1s = new ArrayList<>();
        Order o1 = new Order();
        o1.setId(100L);
        o1.setOrderName("水瓶");
        o1s.add(o1);
        UserPo u1 = new UserPo();
        u1.setId(1L);
        u1.setAge(12);
        u1.setUserName("tom");
        u1.setPassword("1");
        //持有的是同一个order引用
        u1.setOrders(o1s);
        UserPo u2 = new UserPo();
        u2.setId(2L);
        u2.setAge(12);
        u2.setUserName("tom");
        u2.setPassword("2");
        //持有的是同一个order引用
        u2.setOrders(o1s);
        userPos.add(u1);
        userPos.add(u2);
        System.out.println(JSON.toJSONString(userPos));
    }
    @Data
    public static class UserPo {
        private Long id;
        private String userName;
        private String password;
        private Integer age;
        private List<Order> orders;
    }
}
响应报文:
[{"age":12,"id":1,"orders":[{"id":100,"orderName":"水瓶","price":0.0}],"password":"1","userName":"tom"},{"age":12,"id":2,"orders":[{"$ref":"$[0].orders[0]"}],"password":"2","userName":"tom"}]
2. 解决方案
方案一:通过对象拷贝的方式,使得同一个对象的属性值复制到不同的对象中。
方案二:关闭FastJson的循环引用的检查:
JSON.toJSONString(userPos, SerializerFeature.DisableCircularReferenceDetect)
3. 项目中实际遇到的场景
在实际项目中,我们一般会避免案例代码中的书写方式。
但是还是可能会遇到{"$ref":"$[0]"}。
- 查询某接口,得到详细数据(无序且存在重复的元素(重复的元素不是同一个引用))。
 - 需要对详细数据排序:
2.1 将详细数据转换成Map(注意:此时重复的元素只会保留一个)。
2.2 遍历有序的数据,将详细数据排序(此处会造成多个元素持有一个map中的value引用)。 - 使用FastJson对2的返回结果格式化。
 
此时,JSON格式化数据的解决方案就是在序列化对象的同时,使用SerializerFeature.DisableCircularReferenceDetect(关闭引用检查)。










