zoukankan      html  css  js  c++  java
  • FastJson 处理json数据中对象相互引用,最后转为json字符串出现占位符("$ref"标识循环引用)"的问题

    环境

    fastjson 1.2.41

    问题说明

    FastJson 问题
    在json对象中有多个地方引用了相同的对象,在经过几次转换转为json字符串的时候会出现占位符,
    然后使用fastjson 解析字符串也能正确解析,但使用其他json类库解析,无法正常还原数据,还是占位符

    测试代码

    /**
         * FastJson 问题
         * 测试 JSONArray(几个元素有关联,引用了相同得对象) -> 转为List -> 加入到 JSONObject 中 -> 最后转为 json 字符串 打印的时候(最后一步得时候会出现占位符)
         * -> 然后再转为 JSONObject 的时候,非FastJson解析会出现问题(fastJson 解析正常,但是其他json类库处理时,不会对占位符处理,最后直接就原样的将值解析成占位符)
         * 测试
         * testTransfer1  仅仅数据一样,但是实际上是几个不同的对象(数据相同,对象不同),经过上述变化,未出现占位符
         * testTransfer2  是从某一元素上取得数据(同一个对象,在json对象中,多个地方都有引用)在添加到该jsonArray 上,经过上述变化,会出现占位符
         */
        @Test
        public void name() {
    //        testTransfer1();
            testTransfer2();
        }
    
        private void testTransfer1() {
    //        [{"one":1,"two":2,"tickets":[{"one":2,"two":3},{"one":3,"two":4}]},{"one":2,"two":3},{"one":3,"two":4}]
    
            String str = "[{"one":1,"two":2,"tickets":[{"one":2,"two":3},{"one":3,"two":4}]},{"one":2,"two":3},{"one":3,"two":4}]";
            JSONArray array = JSON.parseArray(str);
            List<Object> objects = array.toJavaList(Object.class);
    
            JSONObject object = new JSONObject();
            object.put("list", objects);
            System.out.println(object);
    
            // 经过测试发现如果,不直接用从某个元素中取数据,在添加到该jsonArray 本身,即使他们数据有重合的(数据相同,但不是同一个对象),也不会出现 占位符的现象
        }
    
    
        private void testTransfer2() {
    //         [{"one":1,"two":2,"tickets":[{"one":2,"two":3},{"one":3,"two":4}]]
    
            String str = "[{"one":1,"two":2,"tickets":[{"one":2,"two":3},{"one":3,"two":4}]}]";
            JSONArray array = JSON.parseArray(str);
            // 这里添加
            JSONArray tickets = array.getJSONObject(0).getJSONArray("tickets");
            for (int i = 0; i < tickets.size(); i++) {
                array.add(tickets.get(i));
            }
    
            List<Object> list = array.toJavaList(Object.class);
    
    //      以下代码说明 FastJson 在之后 转为 json 字符串 ,然后再解析为 json 对象时处理正常(能正常解析)
            JSONObject object = new JSONObject();
            object.put("list",list);
            String jsonStr = object.toJSONString();
            System.out.println(jsonStr);
            JSONArray list1 = JSON.parseObject(jsonStr).getJSONArray("list");
            System.out.println(list1);
    
            // 切换 为 其他 json类库处理,例如:jackson
            ObjectMapper mapper = new ObjectMapper();
            try {
                Object o = mapper.readValue(jsonStr, Object.class);
                System.out.println(o);
            } catch (JsonProcessingException e) {
                e.printStackTrace();
            }
    
            // 内部 从 某一个 元素取出数据,在添加到 jsonArray 上, 经过 上述转换 (JSONArray(几个元素有关联) -> 转为List -> 加入到 JSONObject 中 -> 转为 json 字符串),最后会变成这样
            // {"list":[{"tickets":[{"one":2,"two":3},{"one":3,"two":4}],"one":1,"two":2},{"$ref":"$.list[0].tickets[0]"},{"$ref":"$.list[0].tickets[1]"}]}
        }
    
    

    解决办法

        /**
         * 禁用 fastjson 的 循环引用检测
         * 使用 SerializerFeature.DisableCircularReferenceDetect
         */
        private void testTransfer3() {
            String str = "[{"one":1,"two":2,"tickets":[{"one":2,"two":3},{"one":3,"two":4}]}]";
            JSONArray array = JSON.parseArray(str);
            // 这里添加
            JSONArray tickets = array.getJSONObject(0).getJSONArray("tickets");
            for (int i = 0; i < tickets.size(); i++) {
                array.add(tickets.get(i));
            }
    
            // 全局关闭
    //        JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
    
            // 该次解析关闭
            // 转为 json 字符串的时候,禁用了 fastjson 的 循环检测引用特性
            String s = array.toJSONString(array, SerializerFeature.DisableCircularReferenceDetect);
    //        System.out.println(array.toJSONString());
            System.out.println(s);
        }
    

    说明

    由于springboot 默认使用 jackson 处理json 请求,所以需要注意
    由于时间问题,这个地方只是发现情况会出现这种问题,至于对象引用会不会出现这种问题,没有进行实验,也没有对fastjson 源码进行解读

  • 相关阅读:
    MT4系统自带指标代码
    [转载]一个鼠标键盘控制两台甚至多台主机的方法
    国内外证券交易系统开发平台比较
    Win8系统下MT4不能添加指标无法找到技术指标
    Unable to locate package错误解决办法
    ubuntu 常见错误--Could not get lock /var/lib/dpkg/lock
    ubuntu永久修改主机名
    Ant之build.xml详解
    Memory和Storage有什么区别?
    ubuntu下创建eclipse桌面快捷方式
  • 原文地址:https://www.cnblogs.com/kzcming/p/14335419.html
Copyright © 2011-2022 走看看