2013-03-22 137 views
28

我的服務器JSON返回兩個不同類型的DateFormat。 「MMM DD,YYYY」 和 「MMM DD,YYYY HH:MM:SS」Gson到兩個DateFormat的json轉換

當我轉換JSON具有以下是罰款:

Gson gson = new GsonBuilder().setDateFormat("MMM dd, yyyy").create(); 

但是,當我想知道更詳細的日期格式它改變了這一點,它拋出異常com.google.gson.JsonSyntaxException:2013年3月21日

Gson gson = new GsonBuilder().setDateFormat("MMM dd, yyyy HH:mm:ss").create(); 

有沒有辦法爲GSON處理兩個不同的日期格式爲它的JSON的轉換?

回答

60

我正面臨同樣的問題。這是通過自定義反序列化我的解決方案:

new GsonBuilder().registerTypeAdapter(Date.class, new DateDeserializer()); 

private static final String[] DATE_FORMATS = new String[] { 
     "MMM dd, yyyy HH:mm:ss", 
     "MMM dd, yyyy" 
}; 


private class DateDeserializer implements JsonDeserializer<Date> { 

    @Override 
    public Date deserialize(JsonElement jsonElement, Type typeOF, 
      JsonDeserializationContext context) throws JsonParseException { 
     for (String format : DATE_FORMATS) { 
      try { 
       return new SimpleDateFormat(format, Locale.US).parse(jsonElement.getAsString()); 
      } catch (ParseException e) { 
      } 
     } 
     throw new JsonParseException("Unparseable date: \"" + jsonElement.getAsString() 
       + "\". Supported formats: " + Arrays.toString(DATE_FORMATS)); 
    } 
} 
2

自定義反序列化是必要的。一個體面的解決方案是使用Apache Commons DateUtil,它可以一次處理多種日期格式。此外,JodaTime API可能具有類似的功能。

4

雖然答案已被接受,我想分享一個類似但更擴展的解決方案。您可以找到gist here

DateDeserializer.java

public class DateDeserializer<T extends Date> implements JsonDeserializer<T> { 

    private static final String TAG = DateDeserializer.class.getSimpleName(); 

    private final SimpleDateFormat mSimpleDateFormat; 
    private final Class<T> mClazz; 

    public DateDeserializer(SimpleDateFormat simpleDateFormat, Class<T> clazz) { 
     mSimpleDateFormat = simpleDateFormat; 
     mClazz = clazz; 
    } 

    @Override 
    public T deserialize(JsonElement element, Type arg1, JsonDeserializationContext context) throws JsonParseException { 
     String dateString = element.getAsString(); 
     try { 
      T date = mClazz.newInstance(); 
      date.setTime(mSimpleDateFormat.parse(dateString).getTime()); 
      return date; 
     } catch (InstantiationException e) { 
      throw new JsonParseException(e.getMessage(), e); 
     } catch (IllegalAccessException e) { 
      throw new JsonParseException(e.getMessage(), e); 
     } catch (ParseException e) { 
      throw new JsonParseException(e.getMessage(), e); 
     } 
    } 
} 

然後註冊不同的格式爲...

sGson = new GsonBuilder() 
        .registerTypeAdapter(Event.EventDateTime.class, 
          new DateDeserializer<Event.EventDateTime>(
            Event.EventDateTime.DATE_FORMAT, Event.EventDateTime.class)) 
        .registerTypeAdapter(Event.StartEndDateTime.class, 
          new DateDeserializer<Event.StartEndDateTime>(
            Event.StartEndDateTime.DATE_FORMAT, Event.StartEndDateTime.class)) 
        .registerTypeAdapter(Event.SimpleDate.class, 
          new DateDeserializer<Event.SimpleDate>(
            Event.SimpleDate.DATE_FORMAT, Event.SimpleDate.class)) 
        .create(); 

每個格式被映射到一個類...

public class Event { 

    @SerializedName("created") 
    private EventDateTime mCreated; 

    //@SerializedName("updated") 
    private EventDateTime mUpdated; 

    ... 

    @SerializedName("start") 
    private ConditionalDateTime mStart; 

    @SerializedName("end") 
    private ConditionalDateTime mEnd; 

    public static class ConditionalDateTime { 
     @SerializedName("dateTime") 
     private StartEndDateTime mDateTime; 

     @SerializedName("date") 
     private SimpleDate mDate; 

     public SimpleDate getDate() { 
      return mDate; 
     } 

     public StartEndDateTime getDateTime() { 
      return mDateTime; 
     } 

     /** 
     * If it is an all day event then only date is populated (not DateTime) 
     * @return 
     */ 
     public boolean isAllDayEvent() { 
      return mDate != null; 
     } 
    } 

    public static class EventDateTime extends Date { 
     public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"); 
    } 

    public static class StartEndDateTime extends Date { 
     public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ"); 
    } 

    public static class SimpleDate extends java.util.Date { 
     public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd"); 
    } 
} 
+0

非常好的溶液,並且更具可擴展性。 – 2016-05-11 11:58:36

+1

我非常喜歡這個,但我想知道是否可能存在SimpleDateFormats和線程安全問題。如果是這樣,也許最簡單的方式來存儲格式字符串,並在DateDeserializer.deserialize()的每個調用中創建一個新的SimpleDateFormat? – 2016-10-25 23:43:16