关于数据序列化(4),FastJson的两个bug

来源:互联网 发布:与外国人学外语知乎 编辑:程序博客网 时间:2024/05/17 10:54

bug1 fastJson循环引用引发一个bug

fastJson可以将一个对象序列化为json,也可以通过反序列化出一个完整的对象。且支持循环引用。

package com.sincetimes.website.core.common.support;import com.sincetimes.website.core.common.vo.ToStringAbstract;/** ::new */public class DataSimpleVO {    public String name;    public Object value;    public Object value1;    public DataSimpleVO() {    }    public DataSimpleVO(String name, Object value) {    this.name = name;    this.value = value;    }    @Override    public String toString() {    return "DataSimpleVO [name=" + name + ", value=" + value + ", value1=" + value1 + "]";    }}
    DataSimpleVO a = new DataSimpleVO("a", 1);    DataSimpleVO b = new DataSimpleVO("b", 2);    b.value = a;    Map<String, Object> map = new HashMap<>();    map.put(a.name, a);    b.value1 = map;    String jsonStr = JSON.toJSONString(b);    System.out.println(jsonStr);    DataSimpleVO obj = JSON.parseObject(jsonStr, DataSimpleVO.class);    System.out.println(obj.toString());

执行结果

{"name":"b","value":{"name":"a","value":1},"value1":{"a":{"$ref":"$.value"}}}DataSimpleVO [name=b, value={"name":"a","value":1}, value1={"a":{"name":"a","value":1}}]

反序列化成功

改一下代码

    DataSimpleVO a = new DataSimpleVO("a", 1);    DataSimpleVO b = new DataSimpleVO("b", 2);    b.value1 = a;    Map<String, Object> map = new HashMap<>();    map.put(a.name, a);    b.value = map;    String jsonStr = JSON.toJSONString(b);    System.out.println(jsonStr);    DataSimpleVO obj = JSON.parseObject(jsonStr, DataSimpleVO.class);    System.out.println(obj.toString());

执行结果

{"name":"b","value":{"a":{"name":"a","value":1}},"value1":{"$ref":"$.value.a"}}DataSimpleVO [name=b, value={"a":{"name":"a","value":1}}, value1=null]

b中的value1为空,反序列化失败

bug2 要序列化的类含有Class类型属性引起的循环递归无法结束最后内存溢出

要序列化、反序列化的类

public class Request implements Serializable {    private static final long serialVersionUID = -3145939364922415428L;    private Class<?> clazz;    private String method;    private Object param;    public Class<?> getClazz() {    return clazz;    }    public void setClazz(Class<?> clazz) {    this.clazz = clazz;    }    public String getMethod() {    return method;    }    public void setMethod(String method) {    this.method = method;    }    public Object getParam() {    return param;    }    public void setParam(Object param) {    this.param = param;    }    public Object invoke(Object bean) throws Exception {    return clazz.getMethod(method, param.getClass()).invoke(bean, param);    }}

触发bug

Request r = new Request();    r.setClazz(Integer.class);    String s = JSON.toJSONString(r, SerializerFeature.WriteClassName);    System.out.println(s);    JSON.parseObject(s);//bug 触发

我们看看内部

    public static JSONObject parseObject(String text) {        Object obj = parse(text);        if (obj instanceof JSONObject) {            return (JSONObject) obj;        }        return (JSONObject) JSON.toJSON(obj);    }

如果改为JSON.parseObject(s, Request.class);或者直接使用JSON.parse(str)就没问题。

最后的建议:
不要使用JSON.parseObject(…)只使用JSON.parse(str);