gson线上环境解析日期时报错JsonSyntaxException
遇到问题:
问题发生在新功能上线的那一天,所有的测试工作都测试完了,测试还挺顺利,比以往结束的早很多,正高高兴兴的聊着今天可以早回家了。
正高兴着往ST环境部署,部署上去前端一测试却返回了服务器异常,服务器异常信息是这样的:
是用了gson解析json串,解析过程中出现了JsonSyntaxException,也给出了待解析的数据值,是一个常见的日期字符串“2018-03-14 00:00:00”。
这时候第一反应是,测试覆盖不够,没有测试到这种情况?或者是测试偷懒了,每次都用的假数据,没有完整走完测试路径?
虽然是第一想法,但是,作为有经验的开发,我们应该相信测试的专业度,以及测试最基本的功能测试,况且是正向流程的测试,是不会出现问题的。在遇到问题时,我们应该首先选择相信同事。
这种情况,还有另外一种可能性就是测试环境和线上环境不一样。
应急处理:
从上述两个问题出发,一个是确认同事真的走了完整的测试流程;另一个是确认测试和ST环境有什么不同。
第一个问题,从提测开始的请求日志进行了逐个的查看,发现测试的最后两天确实请求了同样的接口,并且返回了正确的数据,说明这个问题不是测试的锅,而是开发自己的锅。
经过百度和google搜索,发现有不少人遇到了同样的异常,问题的原因是因为服务器的Locale不一样导致的,也就是说gson解析日期的方法是会受到Locale影响的。
但是对比测试服务器和线上服务器的Locale发现是一样的,那么想从根本解决问题就变的比较难以下手。
为了赶上上线的节点,我们选择了把日期解析成字符串类型,然后在返给前端之前再使用joda的DateTimeFormatter进行一次日期格式的解析。迅速修改,迅速上线。
追寻原因:
做为非算法类工程师,唯一能够迅速提升的方法就是:抓住问题,不断深挖,找到问题的原因,解决问题。所以,放过这个问题,绝对是巨大的损失。
打开gson的源代码,找到抛出异常的位置:
可以看到抛出JsonSyntaxException是由于ISO8601Utils.parse方法内部出现的异常。再进入到parse方法中,发现它的功能很强大,但是可解析的日期格式却不包含我们的日期字符串样式:
ISO 8601是国际标准化组织提出的日期和时间的国际标准表示方法。从gson中的parse方法来看,大致逻辑是这样的:
1.如果日期值只有年月日(yyyy-MM-dd或者yyyyMMdd),直接返回年月日对应的Date对象;
2.如果日期字符串解析完年月日之后,还有多余的字符,那么按照有time zone进行解析,并获取time zone;
问题就出在第二点上,我们的日期格式除了年月日字符之外还有时分秒字符,但是却没有timezone标记。从源代码来看,我们的日期字符串不可能被成功解析,也就是测试环境也应该出异常才合理。
继续,我们做了一个做简单的示例程序,只有一个main方法,使用gson对我们的日期字符串”{“dt”:”2018-03-14 00:00:00”}”进行解析。
结果是:在台式开发机上确实没有异常,但是放到服务器上运行就会报异常。有了明确的差异,我们就比较容易定位问题了!
在台式开发机上debug跟踪代码,开发机上没有运行错误的代码行,而是执行了parse中的前半部分代码,我们再回顾一下parse中的代码行:
也就是开发机上执行的代码行是dateFormat.parse(json),说明dateFormats中有能够解析我们的日期格式的DateFormat类型。再跟踪一下dateFormats的初始化的代码:
这里默认初始化了一个Locale.US的dateFormat,初始化了一个默认非US的Locale,还有一个Java90rLater的。
当在开发机上运行的时候,会创建一个Locale=zh_CN.UTF-8的DateFormat是这个解析类,解析了我们的日期字符串“2018-03-14 00:00:00”。
我们的ST环境服务器上采用的是en_US.UTF-8,jdk1.7,所以只要一个Locale.US的日期解析器,他不能解析“2018-03-14 00:00:00”格式的日期字符串。
所以会执行ISO8601.parse去解析,代码逻辑定位清楚了,问题原因就是ST环境服务器上的locale不是中文,所以解析不了“2018-03-14 00:00:00”样式的日期字符串。
然而,我们的测试环境也是en_US.UTF-8的Locale,但为什么测试过程中没有出错呢?
原来,测试环境部署的人用的是Xterm,ST环境部署的人用的是secureCRT,登录到同一台机器上之后,当前shell的Locale是不一样的,所以出现了这种诡异的情况。
好了,解决方案还是保留我们应急的解决方案,也就是gson解析成String日期字符串,再用joda的DateTimeFormatter解析成Date类型。因为这种方案不会受到服务器环境的影响。
当然,你也可以像这篇博客那样去改服务器的默认Locale。只是这样的话,仍然存在风险,比如,其他人用的shell客户端登录之后,当前shell默认成en_US就会有问题了!
同类对比:
那么,jackson有没有同样的问题呢?jackson解析日期也需要指定特定的解析器才行,如果用默认的解析器,也会遇到类似无法解析的情况,比如这篇博客写到的案例。
gson线上环境解析日期时报错JsonSyntaxException相关推荐
- vue3 全局注册app.config.globalProperties, 如何处理getCurrentInstance 上下文线上环境报错
vue3挂载全局属性和方法,使用app.config.globalProperties, 但是在组件中获取全局上下文的时候getCurrentInstance会在线上环境报错. 搜索了一遍,看了好多文 ...
- 记一次线上环境 redis偶尔连接超时报错 解决
记一次线上环境 redis偶尔连接超时报错 解决 贴出本地控制台日志 说实话,很痛苦,跟进很久了,一直认为的jvm程序所使用的配置的连接池框架问题 因为程序为 springboot 2 spring ...
- 线上环境ip2region解析ip归属地不对以及searcher.btreeSearch报空指针的两个问题探究
今天在做系统日志的功能时,需要根据ip获取客户端的归属地,于是决定使用ip2region工具来实现,但是在实际使用过程中(使用场景见springboot+aop+线程池+ip2region+mybat ...
- Solr线上环境 Error from server at http://ip:port/solr/core: Expected mime type application/oc
在线上环境用关键字查找时报错. org.apache.solr.client.solrj.impl.HttpSolrClient$RemoteSolrException: Error from ser ...
- doctor mysql数据导入_线上环境mysql主从同步的搭建过程
之前搭建过一套主从同步的mysql集群,但是是基于新数据库,而这次线上环境要升级成主从同步的集群,记录一下升级过程和中间遇到的各种问题. 由于是直接对线上数据库进行修改,因此要保证对线上环境造成尽量小 ...
- html ico不显示,vue 项目线上环境 出现 favicon.ico 不显示 怎么办
vue 项目线上环境 出现 favicon.ico 不显示 怎么办? 一直提示报错: GET HTTP: xxx.xxxx.xxx.xxx:8080/favicon.ico 404 (Not Foun ...
- 用HTMLParser解析html时报错:No module named 'htmlentitydefs'
python3.6用HTMLParser解析html时报错 No module named 'htmlentitydefs'或No module named 'markupbase' 先上代码 fro ...
- 记几次 [线上环境] Dubbo 线程池占满原因分析(第三次:GC STW)
[线上环境] Dubbo 线程池占满原因排查系列 记几次 [线上环境] Dubbo 线程池占满原因分析(第一次:HttpClient) 记几次 [线上环境] Dubbo 线程池占满原因分析(第二次:C ...
- mysql线上教程_线上环境mysql主从同步的搭建过程
之前搭建过一套主从同步的mysql集群,但是是基于新数据库,而这次线上环境要升级成主从同步的集群,记录一下升级过程和中间遇到的各种问题. 由于是直接对线上数据库进行修改,因此要保证对线上环境造成尽量小 ...
最新文章
- [Leetcode] Insertion Sort List
- Webbrowers控件的小技巧
- 交叉验证(Cross Validation)方法思想简介
- cdev linux_Linux设备管理(二)_从cdev_add说起
- 如何选择高性能的数据分析工具,你需要看看数据架构的进化史!
- 关于那些表单的验证码
- 利用jsoup 如何从网页中下载图片
- VUE day_08(7.26)学子商城项目详细版
- ISO 9000 族标准的构成
- java常见面试考点(九):SSM面试题
- css3参考手册在线和下载
- 最小二乘法曲线拟合+C代码
- 商业银行2022年12月升级UKEY证书后故障
- c语言计算个人成绩平均分,C语言 | 计算总平均分及第n个人的成绩
- RT-Thread柿饼控件(5)-- ProgressBar
- 个人微信号API接口搜集
- linux系统u盘格式化命令,如何用LINUX命令格式化U盘
- Linux常用命令和shell命令
- css3实现0.5px边框、圆角渐变色边框+圆角渐变色背景
- matlab 遗传算法工具箱(GATBX)
热门文章
- 猿辅导python辅导老师_【猿题库/猿辅导课程设计面试】python 教研不推荐去猿辅导-看准网...
- 英语四六级作文句型收集
- 新浪企业邮箱服务器怎么设置,新浪企业邮箱|客户端使用
- 新浪邮箱开启POP3/SMTP服务
- 硬件课程设计—电梯控制系统
- PSS E 3.0(大型电力系统仿真计算软件).rar
- 大厦设计师 -- 建造者模式 (Builder Pattern) 介绍 使用案例场景分析 优缺点 及代码演示
- 主叫线路识别限制CLIR
- 2022-2028全球与中国防弹汽车玻璃市场现状及未来发展趋势
- Rdlc报表纵向与横向打印问题