91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何排查GSON時間問題

發布時間:2021-10-09 14:47:45 來源:億速云 閱讀:152 作者:iii 欄目:編程語言

這篇文章主要講解了“如何排查GSON時間問題”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“如何排查GSON時間問題”吧!

問題描述

近期有一個老項目在測試環境中頻繁出現了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反序列化失敗;

背景說明

因為此系統數據量比較大,所有會將半年前的數據歸檔到Hbase中,歸檔的時候會將數據庫中的數據序列化為json格式,然后保存到Hbase中;如果是近期半年的數據會直接查詢數據庫,如果是很早的數據才會查詢Hbase,所以出現的概率比較低;

問題分析

本地重現

為了方便分析,直接把Json串拷貝到本地,然后再本地進行重現,再進行問題分析,Json串比較長,這里使用如下Json串代替:

{"date":"2021-05-14 14:59:37"}

準備相關代碼如下所示:

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;
}

執行的結果是可以反序列成功,并沒有出現上面的錯誤,為了找出原因,這里需要分析一下Gson時間轉換的相關源碼;

源碼分析

Gson時間轉換的源碼還是比較簡單的,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;轉換的時候也是按照這個順序進行轉換,哪個能轉換成功就直接返回,以上出現問題說明三種DateFormat都沒有轉換成功;本地調試可以直接Debug進來,可以發現直接使用localFormat就轉換成功了,并且可以分別查看每個的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格式,所以可以直接轉換成功;可以發現localFormat其實是和本地系統的語言環境有關,所以會出現本地運行結果和服務器運行結果不一致;

再次重現

可以直接通過代碼設置語言環境,把環境設置為Locale.US

public class GsonDate {
	public static void main(String[] args) {
		System.out.println("默認:"+Locale.getDefault());
		System.out.println("重置語言環境: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);
	}
}

運行以上代碼,出現了和服務器一樣的反序列時間問題:

默認:zh_CN
重置語言環境: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)

可以發現我們本地的環境一般都是zh_CN,對應Locale.CHINA

問題解決

系統配置

可以直接改變系統語言環境,liunx可以直接在/etc/sysconfig/i18n中配置:

英文版系統:
LANG="en_US.UTF-8"
中文版系統:
LANG="zh_CN.UTF-8"

可以查看當前配置的語言環境:

[root@Centos ~]# echo $LANG
en_US.UTF-8
代碼實現

可以給Gson設置默認的日志轉換格式:

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);

結果是不僅yyyy-MM-dd HH:mm:ss格式能被解析,包含中文的年月日都可以被解析;如果查看相關源碼可以發現,fastjson并沒有直接使用DateFormat去做日期格式轉換,而是實現了ISO 8601標準,并且提供了中國常見日期格式的支持;具體可以直接查看源碼JSONScanner中的scanISO8601DateIfMatch方法; 另外一點需要說明的是以上GSON使用的是2.2.2版本,最新版本2.8.6版本中同樣提供了對ISO 8601標準的支持,具體可以查看ISO8601Utils類。

感謝各位的閱讀,以上就是“如何排查GSON時間問題”的內容了,經過本文的學習后,相信大家對如何排查GSON時間問題這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

长乐市| 文安县| 华池县| 卢湾区| 北辰区| 石河子市| 体育| 江川县| 新邵县| 霸州市| 绥德县| 巨野县| 马尔康县| 大冶市| 吴堡县| 濮阳县| 察雅县| 盐山县| 固镇县| 宾阳县| 盈江县| 民丰县| 昭苏县| 鞍山市| 文成县| 苏尼特右旗| 云霄县| 宁化县| 英吉沙县| 琼结县| 罗源县| 嫩江县| 西充县| 长岛县| 连南| 丹阳市| 黄陵县| 呼伦贝尔市| 岐山县| 化德县| 宜城市|