這篇文章主要講解了“如何排查GSON時間問題”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何排查GSON時間問題”吧!
創(chuàng)新互聯(lián)建站-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比吳江網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式吳江網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋吳江地區(qū)。費用合理售后完善,10年實體公司更值得信賴。
近期有一個老項目在測試環(huán)境中頻繁出現(xiàn)了GSON反序列化時間問題,錯誤堆棧如下所示:
Exception in thread "main" com.google.gson.JsonSyntaxException: 2021-05-14 14:59:37 at com.google.gson.internal.bind.DateTypeAdapter.deserializeToDate(DateTypeAdapter.java:81) at com.google.gson.internal.bind.DateTypeAdapter.read(DateTypeAdapter.java:66) at com.google.gson.internal.bind.DateTypeAdapter.read(DateTypeAdapter.java:41) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.read(ReflectiveTypeAdapterFactory.java:93) at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:172) at com.google.gson.Gson.fromJson(Gson.java:795) at com.google.gson.Gson.fromJson(Gson.java:761) at com.google.gson.Gson.fromJson(Gson.java:710) at com.google.gson.Gson.fromJson(Gson.java:682) at com.gson.GsonDate.main(GsonDate.java:17) Caused by: java.text.ParseException: Unparseable date: "2021-05-14 14:59:37" at java.text.DateFormat.parse(DateFormat.java:366) at com.google.gson.internal.bind.DateTypeAdapter.deserializeToDate(DateTypeAdapter.java:79) ... 9 more
錯誤描述也很詳細,就是GSON在反序列化一段Json串的時候,因為某個時間字符串無法反序列化,導致最終整個Json反序列化失敗;
因為此系統(tǒng)數(shù)據(jù)量比較大,所有會將半年前的數(shù)據(jù)歸檔到Hbase中,歸檔的時候會將數(shù)據(jù)庫中的數(shù)據(jù)序列化為json格式,然后保存到Hbase中;如果是近期半年的數(shù)據(jù)會直接查詢數(shù)據(jù)庫,如果是很早的數(shù)據(jù)才會查詢Hbase,所以出現(xiàn)的概率比較低;
為了方便分析,直接把Json串拷貝到本地,然后再本地進行重現(xiàn),再進行問題分析,Json串比較長,這里使用如下Json串代替:
{"date":"2021-05-14 14:59:37"}
準備相關(guān)代碼如下所示:
public class GsonDate { public static void main(String[] args) { String json = "{\"date\":\"2021-05-14 14:59:37\"}"; GsonDateBean date = new Gson().fromJson(json, GsonDateBean.class); System.out.println(date); } } @Data class GsonDateBean { private Date date; }
執(zhí)行的結(jié)果是可以反序列成功,并沒有出現(xiàn)上面的錯誤,為了找出原因,這里需要分析一下Gson時間轉(zhuǎn)換的相關(guān)源碼;
Gson時間轉(zhuǎn)換的源碼還是比較簡單的,DateTypeAdapter
部分代碼如下所示:
private final DateFormat enUsFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.US); private final DateFormat localFormat = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT); private final DateFormat iso8601Format = buildIso8601Format(); private static DateFormat buildIso8601Format() { DateFormat iso8601Format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); iso8601Format.setTimeZone(TimeZone.getTimeZone("UTC")); return iso8601Format; } private synchronized Date deserializeToDate(String json) { try { return localFormat.parse(json); } catch (ParseException ignored) { } try { return enUsFormat.parse(json); } catch (ParseException ignored) { } try { return iso8601Format.parse(json); } catch (ParseException e) { throw new JsonSyntaxException(json, e); } }
Gson準備了三個DateFormat
,分別是:localFormat,enUsFormat,iso8601Format;轉(zhuǎn)換的時候也是按照這個順序進行轉(zhuǎn)換,哪個能轉(zhuǎn)換成功就直接返回,以上出現(xiàn)問題說明三種DateFormat
都沒有轉(zhuǎn)換成功;本地調(diào)試可以直接Debug進來,可以發(fā)現(xiàn)直接使用localFormat就轉(zhuǎn)換成功了,并且可以分別查看每個的pattern
;
localFormat:yyyy-M-d H:mm:ss
enUsFormat:MMM d, yyyy h:mm:ss a
iso8601Format:yyyy-MM-dd'T'HH:mm:ss'Z'
以上的日期格式完全符合yyyy-M-d H:mm:ss
格式,所以可以直接轉(zhuǎn)換成功;可以發(fā)現(xiàn)localFormat其實是和本地系統(tǒng)的語言環(huán)境有關(guān),所以會出現(xiàn)本地運行結(jié)果和服務(wù)器運行結(jié)果不一致;
可以直接通過代碼設(shè)置語言環(huán)境,把環(huán)境設(shè)置為Locale.US
public class GsonDate { public static void main(String[] args) { System.out.println("默認:"+Locale.getDefault()); System.out.println("重置語言環(huán)境:Locale.US"); Locale.setDefault(Locale.US); String json = "{\"date\":\"2021-05-14 14:59:37\"}"; GsonDateBean date = new Gson().fromJson(json, GsonDateBean.class); System.out.println(date); } }
運行以上代碼,出現(xiàn)了和服務(wù)器一樣的反序列時間問題:
默認:zh_CN 重置語言環(huán)境:Locale.US Exception in thread "main" com.google.gson.JsonSyntaxException: 2021-05-14 14:59:37 at com.google.gson.internal.bind.DateTypeAdapter.deserializeToDate(DateTypeAdapter.java:81)
可以發(fā)現(xiàn)我們本地的環(huán)境一般都是zh_CN
,對應(yīng)Locale.CHINA
;
可以直接改變系統(tǒng)語言環(huán)境,liunx可以直接在/etc/sysconfig/i18n
中配置:
英文版系統(tǒng): LANG="en_US.UTF-8" 中文版系統(tǒng): LANG="zh_CN.UTF-8"
可以查看當前配置的語言環(huán)境:
[root@Centos ~]# echo $LANG en_US.UTF-8
可以給Gson設(shè)置默認的日志轉(zhuǎn)換格式:
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create(); GsonDateBean date = gson.fromJson(json, GsonDateBean.class);
同樣的如果使用其他Json序列化工具,比如fastjson
是否也有這樣的問題那,可以簡單做一個測試:
Locale.setDefault(Locale.US); String json = "{\"date\":\"2021-05-14 14:59:37\"}"; String json2 = "{\"date\":\"2021年05月14日 14:59:37\"}"; JacksonDateBean date = JSON.parseObject(json, JacksonDateBean.class);
結(jié)果是不僅yyyy-MM-dd HH:mm:ss
格式能被解析,包含中文的年月日
都可以被解析;如果查看相關(guān)源碼可以發(fā)現(xiàn),fastjson
并沒有直接使用DateFormat
去做日期格式轉(zhuǎn)換,而是實現(xiàn)了ISO 8601標準,并且提供了中國常見日期格式的支持;具體可以直接查看源碼JSONScanner
中的scanISO8601DateIfMatch
方法; 另外一點需要說明的是以上GSON使用的是2.2.2
版本,最新版本2.8.6
版本中同樣提供了對ISO 8601標準
的支持,具體可以查看ISO8601Utils
類。
感謝各位的閱讀,以上就是“如何排查GSON時間問題”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對如何排查GSON時間問題這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
本文題目:如何排查GSON時間問題
本文地址:http://m.newbst.com/article36/jheesg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供營銷型網(wǎng)站建設(shè)、動態(tài)網(wǎng)站、Google、網(wǎng)站設(shè)計公司、網(wǎng)站營銷、App設(shè)計
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)