作者:贺子江
- 背景介绍
本篇文章是在我的项目迭代的过程中,发现了的一个乏味的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进行打印工夫类型的时候要留神,在业务过程中,如果对工夫类型有要求最好本人进行工夫类型的转换,这样输入既直观又易于控制,时区的解决也更加灵便,门槛还低。当然这也只是我的集体意见,有不同的意见能够交换意见。