2013-03-22 6 views
28

JSONが2つの異なるタイプのDateFormatを返しています。 "MMM ddと、YYYY" と "MMM ddと、YYYYのHH:MM:SS"2つのDateFormatを使用したGsonから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(); 

は、そのJSON変換用の2つの異なるたDateFormatを処理するgsonための方法はありますか?

答えて

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

非常に素晴らしいソリューションを異なるフォーマットを登録します、そしてはるかに拡張可能です。 –

+1

私はこれが大好きですが、SimpleDateFormatsとスレッドの安全性に問題があるかどうかは疑問です。もしそうなら、代わりにフォーマット文字列を保存し、DateDeserializer.deserialize()の各呼び出しで新しいSimpleDateFormatを作成するのが最も簡単でしょうか? –

関連する問題