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 源碼進行解讀


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM