web-dev-qa-db-fra.com

Conversion Gson en Json avec deux DateFormat

Mon serveur JSON revient avec deux types différents de DateFormat. "MMM jj, aaaa" et "MMM jj, aaaa HH: mm: ss"

Quand je convertis le JSON avec ce qui suit, ça va:

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

Mais lorsque je veux le format de date détaillé et que je le change en cela, il lève l'exception com.google.gson.JsonSyntaxException: 21 mars 2013

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

Existe-t-il un moyen pour gson de gérer deux DateFormat différents pour sa conversion Json?

31
wangyif2

J'étais confronté au même problème. Voici ma solution via une désérialisation personnalisée:

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));
    }
}
68
andrew

Bien que la réponse ait été acceptée, je voulais partager une solution similaire mais plus extensible. Vous pouvez trouver le Gist ici .

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

Enregistrez ensuite les différents formats comme ...

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

Chaque format est ensuite mappé sur une classe ...

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");
    }
}
8
JRomero

Une désérialisation personnalisée est nécessaire. Une solution décente serait d'utiliser Apache Commons DateUtil, qui peut gérer plusieurs formats de date à la fois. De plus, l'API JodaTime peut avoir une fonctionnalité similaire.

2
Programmer Bruce