2013-03-22 66 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