真能一快遮百丑?为什么要弃坑 FastJson

Java大联盟

共 3203字,需浏览 7分钟

 ·

2020-08-16 13:15

  Java大联盟

  帮助万千Java学习者持续成长

关注



作者|咔咔侃技术

https://www.toutiao.com/i6815906868183958027


B 站搜索:楠哥教你学Java

获取更多优质视频教程


  一、FastJson为何

首先抄录一段来自官网的介绍:FastJson是阿里巴巴的开源JSON解析库,它可以解析JSON格式的字符串,支持将Java Bean序列化为JSON字符串,也可以从JSON字符串反序列化到JavaBean。

FastJson是Java程序员常用到的类库之一,相信点开这个页面的你,也肯定是程序员朋友。正如其名,“快”是其主要卖点。


  二、真的很快吗?

没有调研就没有发言权,本着“追求真理”的初心,来一轮简单的测试。对比对象选择应用最广泛的Jackson和Google出品的Gson。测试环境选择JDK 8,AMD 3700X,3200MHZ内存。简化实验,只测试简单对象和复杂对象的String转对象、对象转String,调用1千万次的对比结果如下(时间单位是毫秒):

从测试结果看,FastJson确实是最快的,但仅比Jackson快20%左右,Google的Gson是最慢的,差距较大。读到这里,是不是觉得选择FastJson肯定没错啊!如果面试官问为什么选择FastJson?因为快!这一个理由就可以把他顶回去了。

这里的调查研究并不是很充分,没有对内存占用、大文档的测试。

在现代应用程序中,即使最慢的Gson,也是满足需求的;解析文档速度的快慢,并不能作为选型的唯一标准,可能连主要标准都算不上。对IO优化,并行处理等优化措施,比选用一个更快的库更有效。


三、FastJson并没有那么流行

然而,FastJson并没有那么流行,有一个最直观的数据,那就是在Maven的中的引用量,和Jackson和Gson不在一个数量级,和Jackson强大的家族更没法比。

难道我用了一个假的流行的国产类库?在知乎看到了一篇帖子,讨论为什么外国友人不喜欢FastJson。结论就是FastJson是个代码质量不高的国产类库。完全颠覆了我的认知,因为在我的项目中,是经常使用FastJson的,并没有出现什么Bug,而且这段评论是在2016年写的。

抱着怀疑的态度,打开FastJson的地址,看到大家提的Issues。竟然有1283个未解决的Issues。红框标识出来的,我自己拿去研究下,因为我看到下面还有人提了一样的问题。

测试代码如下:

 try {
      String time = "1970-01-01 00:00:00";
      com.alibaba.fastjson.JSONObject jsonObject = new com.alibaba.fastjson.JSONObject();
      jsonObject.put("time", time);

      Timestamp timestamp = jsonObject.getTimestamp("time");
      System.out.println("time:" + timestamp);
  } catch (Exception e) {
      e.printStackTrace();
  }

果然,在采用了最新版本的类库后,如问题描述的,还是有异常。于是就看到了如下的源代码:

if (strVal.endsWith(".000000000")) {
    strVal = strVal.substring(0, strVal.length() - 10);
else if (strVal.endsWith(".000000")) {
    strVal = strVal.substring(0, strVal.length() - 7);
}

if (strVal.length() == 29 && strVal.charAt(4) == '-' && strVal.charAt(7) == '-' && strVal.charAt(10) == ' ' && strVal.charAt(13) == ':' && strVal.charAt(16) == ':' && strVal.charAt(19) == '.') {
    int year = num(strVal.charAt(0), strVal.charAt(1), strVal.charAt(2), strVal.charAt(3));
    int month = num(strVal.charAt(5), strVal.charAt(6));
    int day = num(strVal.charAt(8), strVal.charAt(9));
    int hour = num(strVal.charAt(11), strVal.charAt(12));
    int minute = num(strVal.charAt(14), strVal.charAt(15));
    int second = num(strVal.charAt(17), strVal.charAt(18));
    int nanos = num(strVal.charAt(20), strVal.charAt(21), strVal.charAt(22), strVal.charAt(23), strVal.charAt(24), strVal.charAt(25), strVal.charAt(26), strVal.charAt(27), strVal.charAt(28));
  return new Timestamp(year - 1900, month - 1, day, hour, minute, second, nanos);
}

这段代码有严重的逻辑错误,这样错误的格式,例如:

“1970-01-01 00:00:00.000000000.000000000”

或者

“1970-01-01 00:00:00.000000000.000000”

也能转换成功,而一些正确的格式,例如:

“1970-01-01 00:00:00”,“1970-01-01 00:00:00.000”

却转换失败。

结合知乎上网友的点评,我本人也觉得FastJson并没有那么优秀,另一些深入的点评,例如ASM,我的理解并不深,就不做测试了。


四、弃坑fastjson

在我负责的项目中,因为SpringBoot相关的框架中,应用了Jackson,本着“最少依赖”的原则,json解析应用了Jackson。但是很多同事的代码中,也用了Gson和Fastjson,当然,是没有严格规范要求的结果。

通过今天的一个小小研究,Jackson的流行,是有着内在的原因的。在我们以后的项目中,主推Jackson,逐渐的淘汰Fastjson。


推荐阅读

1、Spring Boot+Vue项目实战

2、B站:4小时上手MyBatis Plus

3、一文搞懂前后端分离

4、快速上手Spring Boot+Vue前后端分离


楠哥简介

资深 Java 工程师,微信号 southwindss

《Java零基础实战》一书作者

腾讯课程官方 Java 面试官今日头条认证大V

GitChat认证作者,B站认证UP主(楠哥教你学Java)

致力于帮助万千 Java 学习者持续成长。




有收获,就在看 
浏览 31
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报