免费观看又色又爽又黄的小说免费_美女福利视频国产片_亚洲欧美精品_美国一级大黄大色毛片

如何排查GSON時間問題

這篇文章主要講解了“如何排查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)的概率比較低;

問題分析

本地重現(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é)果不一致;

再次重現(xiàn)

可以直接通過代碼設(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)配置

可以直接改變系統(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
代碼實現(xiàn)

可以給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)

成都做網(wǎng)站