开发技术-JSON.toJSONString出现{“$ref“:“$[0]“}


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


public class RefFastJson {

    public static void main(String[] args) {
        // 模拟返回的数据
        String str = "{\n" +
                "    \"code\": 200,\n" +
                "    \"data\": {\n" +
                "        \"users\": [\n" +
                "            {\n" +
                "                \"name\": \"死灵\",\n" +
                "                \"sex\": \"男\",\n" +
                "                \"age\": 18\n" +
                "            },\n" +
                "            {\n" +
                "                \"name\": \"骷髅\",\n" +
                "                \"sex\": \"男\",\n" +
                "                \"age\": 20\n" +
                "            },\n" +
                "            {\n" +
                "                \"name\": \"小黑\",\n" +
                "                \"sex\": \"女\",\n" +
                "                \"age\": 38\n" +
                "            }\n" +
                "        ]\n" +
                "    },\n" +
                "    \"msg\": \"操作成功\"\n" +
                "}";

        // 开始使用 JSONObject 处理数据
        JSONObject jsonObject = JSONObject.parseObject(str);
        JSONObject data = jsonObject.getJSONObject("data");

        String users = data.getString("users");
        List<TUser> userList = JSONObject.parseArray(users, TUser.class);
        ArrayList<HashMap<String, Object>> list = new ArrayList<>();

        // TODO 此为情况1,即 HashMap 创建在循环外面
        HashMap<String, Object> hashMap = new HashMap<>();

        userList.forEach((user) -> {
            // TODO 此为情况2,即 HashMap 创建在循环里面
//            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("name", user.getName());
            hashMap.put("sex", user.getSex());
            hashMap.put("age", user.getAge());
            list.add(hashMap);
        });

        System.out.println("list---" + list);
        System.out.println("处理前---" + JSON.toJSONString(list));


    }
}


class TUser {
    private String name;
    private String sex;
    private int age;

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

输出结果

list---[{sex=女, name=小黑, age=38}, {sex=女, name=小黑, age=38}, {sex=女, name=小黑, age=38}]
处理前---[{"sex":"女","name":"小黑","age":38},{"$ref":"$[0]"},{"$ref":"$[0]"}]

发现

bug1-list 中的元素都是同一个对象

bug2-JSON.toJSONString(list) 输出的是{"$ref":"$[0]"}

先看bug2,这是 fastjson 支持循环引用引起的(因为 list 中的3元素都一样)

看中文文档中:Fastjson 循环引用_w3cschool

 提供了两种解决方法 

1、全局配置关闭,即创建一个配置类

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.context.annotation.Configuration;


@Configuration
public class FastJsonConfig {
    static {
        //全局配置关闭 Fastjson 循环引用
        JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.DisableCircularReferenceDetect.getMask();
    }
}

注册到 bean 容器后就会生效

2、局部配置关闭

System.out.println("处理后---" + JSON.toJSONString(list, SerializerFeature.DisableCircularReferenceDetect));

其实 bug2 是由 bug1 引起的,这是因为创建 HashMap 是在循环的外面,改成到里面就没有问题了。


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


public class RefFastJson {

    public static void main(String[] args) {
        // 模拟返回的数据
        String str = "{\n" +
                "    \"code\": 200,\n" +
                "    \"data\": {\n" +
                "        \"users\": [\n" +
                "            {\n" +
                "                \"name\": \"死灵\",\n" +
                "                \"sex\": \"男\",\n" +
                "                \"age\": 18\n" +
                "            },\n" +
                "            {\n" +
                "                \"name\": \"骷髅\",\n" +
                "                \"sex\": \"男\",\n" +
                "                \"age\": 20\n" +
                "            },\n" +
                "            {\n" +
                "                \"name\": \"小黑\",\n" +
                "                \"sex\": \"女\",\n" +
                "                \"age\": 38\n" +
                "            }\n" +
                "        ]\n" +
                "    },\n" +
                "    \"msg\": \"操作成功\"\n" +
                "}";

        // 开始使用 JSONObject 处理数据
        JSONObject jsonObject = JSONObject.parseObject(str);
        JSONObject data = jsonObject.getJSONObject("data");

        String users = data.getString("users");
        List<TUser> userList = JSONObject.parseArray(users, TUser.class);
        ArrayList<HashMap<String, Object>> list = new ArrayList<>();

        // TODO 此为情况1,即 HashMap 创建在循环外面
//        HashMap<String, Object> hashMap = new HashMap<>();

        userList.forEach((user) -> {
            // TODO 此为情况2,即 HashMap 创建在循环里面
            HashMap<String, Object> hashMap = new HashMap<>();
            hashMap.put("name", user.getName());
            hashMap.put("sex", user.getSex());
            hashMap.put("age", user.getAge());
            list.add(hashMap);
        });

        System.out.println("list---" + list);
        System.out.println("处理前---" + JSON.toJSONString(list));
        System.out.println("处理后---" + JSON.toJSONString(list, SerializerFeature.DisableCircularReferenceDetect));

    }
}


class TUser {
    private String name;
    private String sex;
    private int age;

    public String getName() {
        return name;
    }

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

    public String getSex() {
        return sex;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

输出结果

list---[{sex=男, name=死灵, age=18}, {sex=男, name=骷髅, age=20}, {sex=女, name=小黑, age=38}]
处理前---[{"sex":"男","name":"死灵","age":18},{"sex":"男","name":"骷髅","age":20},{"sex":"女","name":"小黑","age":38}]
处理后---[{"sex":"男","name":"死灵","age":18},{"sex":"男","name":"骷髅","age":20},{"sex":"女","name":"小黑","age":38}]

可以看到,bug1 改好后 bug2 就不出现了。

所以出现这个 {"$ref":"$[0]"} 建议检查是否在处理循环时,创建对象的时机不对

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值