基於Gson的Http請求解析long型日期時出錯的解決方案
阿新 • • 發佈:2019-01-22
在http的post方法中,我們通常使用Gson來實現物件和Json的相互轉換。然而,原生的Gson在將包含Date型別物件序列化的過程中,會自動將Date型別轉換為long型。此時若想反序列化物件,則Gson將會丟擲一個JsonSyntaxException,表示解析失敗。
那麼為什麼會失敗呢?通過檢視原始碼可知,Gson預設的日期介面卡DateTypeAdapter,只支援這種“yyyy-MM-dd'T'HH:mm:ss'Z'”的字串日期格式,如圖1所示。
圖1
因此,我們可通過重寫DateTypeAdapter來達到解析long型日期格式的目的。首先實現Json的反序列化介面,然後重寫deserialize方法,同時我們還可通過構造器傳入DateFormat物件,以支援特定字串日期格式的解析,如圖2所示。
圖2
最後附上完整的的http工具類(post方法),希望對大家有所幫助。
/** * Http工具類 */ public class HttpUtils { private static final Logger logger = LoggerFactory.getLogger(HttpUtils.class); private static final Client CLIENT = Client.create(); private static final Gson GSON = new GsonBuilder() .registerTypeAdapter(Date.class, new DateTypeAdapter()) .create(); private static final String ACCEPT = ": accept: "; private static final String PATH = "path= "; private static final String APPJSON = "application/json"; private static final String RESPONSE = ": response: "; /** * 該方法可轉換複雜的物件(包含複雜引用型別成員變數) * @param path * @param request * @param describe * @param type * @return */ public static T post(String path, Object request, String describe, Type type) { if (request != null) { logger.info("\n" + describe + ACCEPT + request + "\n" + PATH + path); WebResource webResource = CLIENT.resource(path); String response = webResource.accept(APPJSON).type(APPJSON).post(String.class, new Gson().toJson(request)); logger.info("\n" + describe + RESPONSE + response); return GSON.fromJson(response, type); } return null; } /** * 該方法可轉換複雜的物件(包含複雜引用型別成員變數),同時還可新增請求頭資訊 * @param path * @param header * @param request * @param describe * @param type * @return */ public static T postWithHeader(String path, Map<String, String> header, Object request, String describe, Type type) { if (request != null) { logger.info("\n" + describe + ACCEPT + request + "\n" + PATH + path); WebResource webResource = CLIENT.resource(path); Builder builder = webResource.getRequestBuilder(); for (Map.Entry<String, String> entry : header.entrySet()) { builder = builder.header(entry.getKey(), entry.getValue()); } String response = builder.accept(APPJSON).type(APPJSON).post(String.class, new Gson().toJson(request)); logger.info("\n" + describe + RESPONSE + response); return GSON.fromJson(response, type); } return null; } } /** * 重寫日期型別介面卡 * 預設日期型別為Long型,若日期格式為String型別,則必須通過構造器傳入對應DateFormat型別進行日期轉換 */ class DateTypeAdapter implements JsonDeserializer<Date> { private DateFormat format; public DateTypeAdapter() { } public DateTypeAdapter(DateFormat format) { this.format = format; } public synchronized Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { if (!(json instanceof JsonPrimitive)) { throw new JsonParseException("This is not a primitive value"); } String jsonStr = json.getAsString(); if (format != null) { try { return format.parse(jsonStr); } catch (ParseException e) { e.printStackTrace(); } } return new Date(Long.parseLong(jsonStr)); } }