遇到一个 fastjson 赋值问题

原创
05/15 12:44
阅读数 105

        背景:需求有变,定好修改方案,测试发现有一处代码要修改。是一个json 字符串,项目使用的是 fastjson ,此处逻辑是:先取出 一个 JSONObject  obj ,然后从中取出一个 JSONArray  jarr,该 jarr  add 一个 JSONObject类型键值对,然后该 obj  再put  jarr  。还是加个代码片段吧:

JSONObject jobj2 = new JSONObject();
JSONArray jarr2 = jobj2.getJSONArray("4");
JSONObject obj2 = new JSONObject();
obj2.put("taskId", "232323");
jarr2.add(obj2);
jobj2.put("4", jarr2);

        修改1:增加一个判断,某些情况不希望 json 字符串里有这个键值对,由于后续代码还在引用 add  后的 jarr ,所以修改如下:

JSONObject jobj2 = new JSONObject();
JSONArray jarr2 = jobj2.getJSONArray("4");
JSONObject obj2 = new JSONObject();
obj2.put("taskId", "232323");
jarr2.add(obj2);

if(//满足某条件){
    jobj2.put("4", jarr2);
}

        修改后测试发现不符合预期!!! Why ?!

        debug 发现 jarr 执行 add 方法后,obj 里的也已经有这个键值对了。啥都不说了,直接看源码!

        JSONObject 里 getJSONArray 方法

public JSONArray getJSONArray(String key) {
    Object value = this.map.get(key);
    if (value instanceof JSONArray) {
        return (JSONArray)value; //返回该对象里json数组对象的一个引用
    } else if (value instanceof List) {
        return new JSONArray((List)value); //返回一个新的json数组对象
    } else {
        return value instanceof String ? (JSONArray)JSON.parse((String)value) : (JSONArray)toJSON(value);
    }
}

        从上面可知根据 key 获取的值如果是JSONArray 类型的,直接返回该json数组对象的一个引用,使用add 方法时,jarr 被修改,obj 里的值当然跟着变了,完全不需要再去调用 put 方法。

        写个测试代码试试,结果符合预期:

public class TestJson {

    public static void main(String[] args) {
        String str1 = "{\"3\":[{\"index`custId\":\"0\"}]}";
        JSONObject flowDetails = JSONObject.parseObject(str1);

        JSONArray nodeFlowDetails = flowDetails.getJSONArray("3");
        JSONObject obj1 = new JSONObject();
        obj1.put("taskId", "232323");
        nodeFlowDetails.add(obj1);
        System.out.println(flowDetails.toJSONString());
    }
}

        此时一个想法产生:如果这个 jarr 是 List 类型,是不是需要 put 方法,obj 的值才会变呢?

        写个测试代码:

public class TestJson {

    public static void main(String[] args) {
        JSONObject jobj2 = new JSONObject();
        List<Map<String, String>> list = new ArrayList<>();
        Map<String, String> map1 = new HashMap<>();
        map1.put("index", "09986665");
        list.add(map1);
        jobj2.put("4", list);
        JSONArray jarr2 = jobj2.getJSONArray("4");
        JSONObject obj2 = new JSONObject();
        obj2.put("taskId", "232323");
        jarr2.add(obj2);
        System.out.println(jobj2.toJSONString());
    }
}

        结果显示,没有使用put 方法 obj 的值同样会变!!这,,,,,,,接着看源码呗,JSONArray 这个构造方法和add 方法如下:

public JSONArray(List<Object> list) {
    this.list = list;
}
public boolean add(Object e) {
    return this.list.add(e);
}

        发现 jarr  里的 list 和 obj 里的 value 指向同一个对象,jarr  调用 add 方法修改的是这个 list 对象,所以obj 的值也变了!

        最终修改:由于发现项目代码 后面引用 jarr  但是根本不需要,直接修改如下:

JSONObject jobj2 = new JSONObject();
JSONArray jarr2 = jobj2.getJSONArray("4");

if(//满足某条件){
    JSONObject obj2 = new JSONObject();
    obj2.put("taskId", "232323");
    jarr2.add(obj2);
}

        突然发现,看源码挺有意思的!

 

 

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部