alibaba / fastjson

FASTJSON 2.0.x has been released, faster and more secure, recommend you upgrade.
https://github.com/alibaba/fastjson2/wiki/fastjson_1_upgrade_cn
Apache License 2.0
25.75k stars 6.5k forks source link

不“规范”JavaBean序列化toJson时存在$ref引用,反序列化时引用对象找不到,导致类的字段值为空 #1275

Open hiluo opened 7 years ago

hiluo commented 7 years ago

问题出现环境 简化后的数据结构和测试代码如下

public class FooTest {
    public static void main(String[] args) {

        Foo foo = new Foo();
        List<ItemImage> imageList = new ArrayList<ItemImage>();
        ItemImage image = new ItemImage();

        imageList = new ArrayList<ItemImage>();
        image = new ItemImage();
        image.url = "http://g.cn";
        imageList.add(image);
        foo.thumbnails = imageList;
        String jsonString = JSON.toJSONString(foo);         // jsonString的值为 jsonString的值为 {"thumbnail":{"url":"http://g.cn"},"thumbnails":[{"$ref":"$.thumbnail"}]}
        Foo foo1 = JSON.parseObject(jsonString, Foo.class); //thubnails[0]为空
        System.out.println("foo >> " + jsonString);
    }
}

class Foo {
    public List<ItemImage> thumbnails;
    public ItemImage getThumbnail() {
        return thumbnails != null && thumbnails.size() > 0 ? thumbnails.get(0) : null;
    }
}

class ItemImage {
    public String url;
}

案发现场截图 image

是否稳定重现 稳定重现,基于master分支的7eeb764c7d365a8f116e375f43df2d6b089be574 一些小白的分析 类中没有定义字段,在序列化时为什么产生成相关的key ,value对 查看序列化的逻辑,发现其它相关处理get方法的逻辑,会从getXXX中获取XXX来当做key image

反序列化失败的原因: 在反序列化时发现contextArray导常(如下图所示),导致在最后的handleResovleTask时通过$ref查不到相关引用数据,正常contextArray[1]应该是$.thumbnail,其object字段值应该是ItemImage实例吧! image

问题临时解决方案 1)对相关的get方法加如下注解(局部关闭$ref特性) @JSONField(serialzeFeatures = SerializerFeature.DisableCircularReferenceDetect) 2)toSJONString时关闭$ref特性(事务性关闭$ref特性) JSON.toJSONString(需要序列类的实例, SerializerFeature.DisableCircularReferenceDetect); 本质的原因 ????????????

kimmking commented 7 years ago

JSON最佳实践: https://github.com/kimmking/kk/blob/master/technotes/json-best-practice.md