20171122-fastJson、序列化、深拷贝

fastJson过滤器:

fastjson 过滤不需要的字段或者只要某些字段

/*
 * 第一种:在对象响应字段前加注解,这样生成的json也不包含该字段。
 * @JSONField(serialize=false)  
 * private String name;  
 */

/*
 * 第二种:在对象对应字段前面加transient,表示该字段不用序列化,即在生成json的时候就不会包含该字段了。
 * private transient  String name;  
 */

/*
 * 第三种:使用fastjson的拦截器
 * PropertyFilter profilter = new PropertyFilter(){  
  
            @Override  
            public boolean apply(Object object, String name, Object value) {  
                if(name.equalsIgnoreCase("last")){  
                    //false表示last字段将被排除在外  
                    return false;  
                }  
                return true;  
            }  
              
        };  
        json = JSON.toJSONString(user, profilter);  
        System.out.println(json);   
 */

/*
 * 第四种,直接填写属性
 * SimplePropertyPreFilter filter = new SimplePropertyPreFilter(TTown.class, "id","townname");  
    response.getWriter().write(JSONObject.toJSONString(townList,filter));   

 */

工具组同学在做热修复时发现一种robust不能兼容的情况。就是对对象进行序列化,这个对象会根据类的字段和方法自动生成serialVersionUID, robust插入代码后serialVersionUID变掉了,导致反序列化失败。
因为这个整理了下相关文档。
文档:

既然如此,那没有定义serialVersionUID的那些对象,被存入的本地文件,新版本该类改变了类变量,那读取的旧缓存的文件还能正确恢复吗,新添加的字段被恢复成默认值还是直接报InvalidClassException的异常?

那如果是通过fastJson的jsonString存储和恢复呢?因为这种方式是将对象编程键值对的json格式,不是严格意义上序列化,github的说明上也说了,只要是符合JavaBean规范的都可以,不用非要serialVerionUID。demo很简单就可以证明。

具体详细的解释可以参考:Java序列化

平时定义的bean都是json对应的,看样子不怎么符合JavaBean标准。而且如有有复杂对象的拷贝需求,fastJson的方法看起来是最方便最快的。

正好需求中碰到相册数据的深拷贝,用的是序列化的方法做的。想到能不能改成json解析的方法,然后就刚好遇到了个问题。

  1. 序列化方法实现:单个对象clone,列表要在外层循环调用clone方法
    // serializable object
    public static GalleryItem deepCloneGalleryItem(GalleryItem in) {
        try {
            long ss= System.currentTimeMillis();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);
            oos.writeObject(in);
            ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bais);
            LogUtil.v("InLog", "success deepCloneGalleryItem= " + (System.currentTimeMillis() - ss)) ;
            return (GalleryItem) ois.readObject();
        } catch (IOException e) {
            e.printStackTrace();
            LogUtil.e("InLog", "IOException deepCloneGalleryItem");
            return null;
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
            LogUtil.e("InLog", "ClassNotFoundException deepCloneGalleryItem");
            return null;
        }
    }

    @Override
    public void notifyPrepareDataList(List<GalleryItem> list) {
        for (GalleryItem item : list) {
            it = ListUtil.deepCloneGalleryItem(item);
        }
    }
  1. Json转化方法实现:单个对象clone或直接整个列表clone
    public static void cloneJson(GalleryItem in){
        long ss = System.currentTimeMillis();
        String json = JSON.toJSONString(in);
        GalleryItem item = JSON.parseObject(json, GalleryItem.class);
        LogUtil.v("InLog", "cloneJson cost " + (System.currentTimeMillis() - ss));
        LogUtil.v("InLog", "cloneJson in " + in.hashCode() + ",item is  " + item.hashCode());
    }

    public static void cloneJson(List<GalleryItem> in){
        long ss = System.currentTimeMillis();
        String json = JSON.toJSONString(in);
        List<GalleryItem> item = JSON.parseArray(json, GalleryItem.class);
        LogUtil.d("InLog", "cloneJson cost " + (System.currentTimeMillis() - ss));
    }
    
    @Override
    public void notifyPrepareDataList(List<GalleryItem> list) {
        ListUtil.cloneJson(list);
    }

该对象的以上两种方法,json转换的方法并没有更快。1000个对象时间差不多。

使用的fastJson是android版本:'com.alibaba:fastjson:1.1.51.android',因为GalleryItem有个long型字段复写get方法时返回了String,导致JSON.toJSONString(in);一直报错:

Error:
com.alibaba.fastjson.JSONException: write javaBean error
at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:600)
at com.alibaba.fastjson.serializer.JSONSerializer.write(JSONSerializer.java:262)
at com.alibaba.fastjson.JSON.toJSONString(JSON.java:607)
at com.alibaba.fastjson.JSON.toJSONString(JSON.java:334)
..............................................
.....
Caused by: java.lang.ClassCastException: java.lang.Long cannot be cast to java.lang.String
at com.alibaba.fastjson.serializer.JavaBeanSerializer.write(JavaBeanSerializer.java:526)
... 21 more

被这个问题困扰好久,app os:死前我都提示线索了,你怎么还没破案啊。
原因就是get方法返回型和定义的不一样了。所以这种在bean里直接改变返回型的做法不适合在fastJson里用。

    public long duration;
    public String getDuration() {
        try {
            return formatTimeWithMin(duration);
        } catch (NumberFormatException e) {
            return "0:00";
        }
    }

但是在使用新的版本compile com.alibaba:fastjson:1.1.67.android,以上不会出错。应该是修复了该问题,但是在JonsString解析成对象时还是会报类型转换的异常导致转换不成功。所以还是在使用时注意这种情况的转换。

image

附送其他使用注意事项fastjson使用过程中的坑

以及一个容易被忽视的原因分析。
JVM源码分析之不保证顺序的Class.getMethods

当然开源库在更新,新的版本会有不同的优化,注意差异。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容