作者:贺子江
- 背景介绍
本篇文章是在我的项目迭代的过程中,发现了的一个乏味的 bug 所引发进去的源码剖析,在这里以点破面,钻研一下 fastjson 的源码 - 案例剖析
2.1 发现问题的过程
在我的项目应用中,发现对于 Timestamp 的类型进行 toJSONString()办法调用的时候,输入构造并没有依照料想的接果进行展现,后续独自拆出 demo 来进行钻研
public static void main(String[] args) {
Timestamp timestamp = new Timestamp(System.currentTimeMillis());
JSONObject jsonObject = new JSONObject();
jsonObject.put("timestamp",timestamp);
System.out.println(jsonObject.toJSONString());
}
预期:输入 Timestamp 类的 tostring 信息
理论:输入的是 Timestamp 的工夫戳 long 值
2.2 debug 过程和代码剖析
当咱们遇到和咱们想法不一样的时候,就要去看源码到底是怎么实现的。在这里我的第一反馈是 fastjson 的 bug,而后咱们要去验证这是 fastjson 的 bug 还是说这是它本人的策略
调用栈追踪
public String toJSONString() {
SerializeWriter out = new SerializeWriter();
String var2;
try {(new JSONSerializer(out)).write(this);
var2 = out.toString();} finally {out.close();
}
return var2;
}
这里间接 new 啦一个序列化 writer 对象来进行 write 操作,点进去持续看
public final void write(Object object) {
if (object == null) {this.out.writeNull();
} else {Class<?> clazz = object.getClass();
ObjectSerializer writer = this.getObjectWriter(clazz);
try {writer.write(this, object, (Object)null, (Type)null, 0);
} catch (IOException var5) {throw new JSONException(var5.getMessage(), var5);
}
}
}
这里有一个 ObjectSerializer 对象是比拟重要的,这里也是开始进入到了外围办法
这里能够发现 ObjectSerializer 接口有很多的实现类,通过 debug 发现咱们 Timestamp 对应的是序列化类是 DateCodec
点击去持续看,发现真正的实现逻辑一些很显著啦
这里有几个 if else 的判断来实现一些继承了 Date 类的一些类的序列化的操作,其中 WriteDateUseDateFormat WriteClassName UseISO8601DateFormat 这些 SerializerFeature 枚举类占据了很重要的角色,此时咱们终于发现原来 fastjson 对于 date 的实现类有非凡的序列化操作,这里须要咱们进行一些非凡配置来实现 toJSONString 的实现。
2.3 解决方案钻研
1. 遇到 date 的实现类,本人业务应用相干的 tostring 办法,不要应用原生类型,应用 string 代替
2. 配置相干的 SerializerFeature 应用 fastjson 的类进行解决
- 两种计划的比照
3.1 遇到 date 的实现类,本人业务应用相干的 tostring 办法,不要应用原生类型,应用 string 代替
执行后果:
运行工夫:98ms
3.2 配置相干的 SerializerFeature 应用 fastjson 的类进行解决
执行后果:
运行工夫:113ms
- 论断
fastjson 在解决工夫类型的时候其实并没有什么劣势,咱们在应用 fastjson 进行打印工夫类型的时候要留神,在业务过程中,如果对工夫类型有要求最好本人进行工夫类型的转换,这样输入既直观又易于控制,时区的解决也更加灵便,门槛还低。当然这也只是我的集体意见,有不同的意见能够交换意见。