3

I have some entities, which contain some Calendar attributes. I want to serialize it in a way that they are stored as Dates within the GSON serialized JSON, because Mongo can store $date as new ISODate(".."). We did this usually by ignoring the calendar attributes with ExclusionStrategy and set them manually but it became pretty gruesome after a while.

I found some code snippets which should make it work via a custom TypeAdapter.

This is my CalendarDateTypeAdapter.

public class CalendarDateTypeAdapter extends TypeAdapter<Calendar> implements JsonSerializer<Calendar>, JsonDeserializer<Calendar> {

private static final Gson gson = new GsonBuilder().create();
private static final TypeAdapter<Date> dateTypeAdapter = gson.getAdapter(Date.class);
private static final String MONGO_UTC_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

public JsonElement serialize(Calendar src, Type type,
        JsonSerializationContext context) {
    if (src == null) {
        return null;
    } else {
        SimpleDateFormat format = new SimpleDateFormat(MONGO_UTC_FORMAT);
        JsonObject jo = new JsonObject();
        jo.addProperty("$date", format.format(src.getTime()));
        return jo;
    }
}

@Override
public Calendar deserialize(JsonElement json, Type type,
        JsonDeserializationContext context) throws JsonParseException {
    Date date = null;
    SimpleDateFormat format = new SimpleDateFormat(MONGO_UTC_FORMAT);
    try {
        date = format.parse(json.getAsJsonObject().get("$date").getAsString());
    } catch (ParseException e) {
        date = null;
    }
    GregorianCalendar gregorianCalendar = new GregorianCalendar();
    gregorianCalendar.setTime(date);
    return gregorianCalendar;
}
    @Override
public void write(JsonWriter out, Calendar value) throws IOException {
    dateTypeAdapter.write(out, value.getTime());
}

@Override
public Calendar read(JsonReader in) throws IOException {
    Date read = dateTypeAdapter.read(in);
    GregorianCalendar gregorianCalendar = new GregorianCalendar();
    gregorianCalendar.setTime(read);
    return gregorianCalendar;
}
}

When I create my gson like:

    GsonBuilder gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeAdapter(GregorianCalendar.class, new CalendarDateTypeAdapter());
    Gson create = gsonBuilder.create();

and try to seralize I get sth like:

{ "dateHarvested" : { "year" : 2015 , "month" : 0 , "dayOfMonth" : 5 , "hourOfDay" : 22 , "minute" : 45 , "second" : 37}

instead of:

"date_harvested" : ISODate("2015-01-05T13:03:56.132Z")

Afterwards when deserializing I would like it to convert it back to a gregorian calendar.

What am I doing wrong?

Ev0oD
  • 1,395
  • 16
  • 33

1 Answers1

7

I had the same issue with GSON. I created a custom serializer for the Calendar object but kept getting the default serializer output when serializing Calendar objects. I solved this by using registerTypeHierarchyAdapter instead of registerTypeAdapter.

GsonBuilder = new GsonBuilder();
build.registerTypeHierarchyAdapter(Calendar.class, new CalendarSerializer());
Gson gson = builder.create();

Hope that helps!

jwinwood
  • 106
  • 5