fastjson一个有趣的bug

本文深入探讨了FastJSON中一个有趣但容易忽视的Bug,当数组中包含不同类型的JSON对象时,修改特定对象的属性可能不会如预期那样反映在原始数组中。文章通过示例代码详细解释了这一现象,并分析了其背后的原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

fastjson一个有趣的bug

今天下午同事找我看一个bug,看完之后觉得非常有意思,所以准备记录一下。原来的代码我就不贴了,比较复杂。我就贴一个简单的重现代码吧。

//创建jsonarray数组
		JSONArray array = new JSONArray();
		//第一个json对象 JSONObject
		com.alibaba.fastjson.JSONObject a = new com.alibaba.fastjson.JSONObject();
		a.put("name", "张三");
		a.put("age", "14");
		array.add(a);
		//第二个json对象
		com.alibaba.fastjson.JSONObject b = new com.alibaba.fastjson.JSONObject();
		b.put("name", "李四");
		b.put("age", "44");
		array.add(b);
		
		//第二个json对象
		net.sf.json.JSONObject c = new net.sf.json.JSONObject();
		c.put("name", "王五");
		c.put("age", "14");
		array.add(c);
		//第二个json对象
		net.sf.json.JSONObject d = new net.sf.json.JSONObject();
		d.put("name", "王五");
		d.put("age", "14");
		array.add(d);
		
		//遍历
		for(int i=0;i<array.size();i++) {
			//如果年龄等于14岁
			if("14".equals(array.getJSONObject(i).get("age"))) {
				//将14岁改成41岁
				array.getJSONObject(i).put("age", "41");
			}
		}
		
		//输出
		for(int i=0;i<array.size();i++) {
			System.out.println("name="+array.getJSONObject(i).get("name"));
			System.out.println("age="+array.getJSONObject(i).get("age"));
		}

你们猜猜结果是什么?下面就是输出结果,是不是和想象的不一样。后面两个王五的age并没有变!!!那为什么前面的变了呢。

name=张三
age=41
name=李四
age=44
name=王五
age=14
name=王五
age=14

带着这样的疑问我就去看源码了。下面是fastjson的源码。他的问题就出在这个 array.getJSONObject(i)获取寄送object

public JSONObject getJSONObject(int index) {
        Object value = list.get(index);

        if (value instanceof JSONObject) {
            return (JSONObject) value;
        }
		//如果这里的object的类型不是com.alibaba.fastjson.JSONObject他会执行toJSON的方法,我们在进这个方法看看
        return (JSONObject) toJSON(value);
    }

下面是截取的一段代码。

 if (javaObject == null) {
            return null;
        }

        if (javaObject instanceof JSON) {
            return javaObject;
        }

        if (javaObject instanceof Map) {
            Map<Object, Object> map = (Map<Object, Object>) javaObject;
			//这里new了一个新的jsonobject对象
            JSONObject json = new JSONObject(map.size());

            for (Map.Entry<Object, Object> entry : map.entrySet()) {
                Object key = entry.getKey();
                String jsonKey = TypeUtils.castToString(key);
                Object jsonValue = toJSON(entry.getValue());
                json.put(jsonKey, jsonValue);
            }
			//这里返回了这个对象
            return json;
        }

从上面的代码就明白了为什么下面两个人的年龄没有变了。因为他的对象不是com.alibaba.fastjson.JSONObject所以在getJSONObject给他创建了一个新的对象。然后你修改的是新的对象的值。你JSONArray里面的对象值并没有改变。所以输出还是原来的。

//创建jsonarray数组
		JSONArray array = new JSONArray();
		//第一个json对象 JSONObject
		com.alibaba.fastjson.JSONObject a = new com.alibaba.fastjson.JSONObject();
		a.put("name", "张三");
		a.put("age", "14");
		array.add(a);
		//第二个json对象
		com.alibaba.fastjson.JSONObject b = new com.alibaba.fastjson.JSONObject();
		b.put("name", "李四");
		b.put("age", "44");
		array.add(b);
		
		//第二个json对象
		net.sf.json.JSONObject c = new net.sf.json.JSONObject();
		c.put("name", "王五");
		c.put("age", "14");
		array.add(c);
		//第二个json对象
		net.sf.json.JSONObject d = new net.sf.json.JSONObject();
		d.put("name", "王五");
		d.put("age", "14");
		array.add(d);
		
		JSONArray array2 = new JSONArray();
		
		//遍历
		for(int i=0;i<array.size();i++) {
			//如果年龄等于14岁
			if("14".equals(array.getJSONObject(i).get("age"))) {
				//将14岁改成41岁
				array.getJSONObject(i).put("age", "41");
				//用一个新的对象接住
				JSONObject e = array.getJSONObject(i);
				e.put("age", "41");
				//添加到另一个数组
				array2.add(e);
			}
		}
		
		//输出
		for(int i=0;i<array.size();i++) {
			System.out.println("name="+array.getJSONObject(i).get("name"));
			System.out.println("age="+array.getJSONObject(i).get("age"));
		}
		System.out.println("====================华丽的分割线=================");
		//输出2
		for(int i=0;i<array2.size();i++) {
			System.out.println("name="+array2.getJSONObject(i).get("name"));
			System.out.println("age="+array2.getJSONObject(i).get("age"));
		}

在看看结果!正常了。

name=张三
age=41
name=李四
age=44
name=王五
age=14
name=王五
age=14
====================华丽的分割线=================
name=张三
age=41
name=王五
age=41
name=王五
age=41

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值