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解析的方法,然后就刚好遇到了个问题。
- 序列化方法实现:单个对象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);
}
}
- 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解析成对象时还是会报类型转换的异常导致转换不成功。所以还是在使用时注意这种情况的转换。
附送其他使用注意事项fastjson使用过程中的坑
以及一个容易被忽视的原因分析。
JVM源码分析之不保证顺序的Class.getMethods
当然开源库在更新,新的版本会有不同的优化,注意差异。