1

I have a Contact class with a created Date property. I'm attempting to do the following:

    Contact received = gson.fromJson(contactJson, Contact.class);

However I get the exception:

 com.google.gson.JsonSyntaxException: 1433444958703
at com.google.gson.internal.bind.DateTypeAdapter.deserializeToDate(DateTypeAdapter.java:81)
at com.google.gson.internal.bind.DateTypeAdapter.read(DateTypeAdapter.java:66)

There is a similar solution to this posted already: "Unparseable date: 1302828677828" trying to deserialize with Gson a millisecond-format date received from server

However it does not work for me (Will not compile).

Gson version 2.3.1

Thoughts?

TIA, - Ole

Community
  • 1
  • 1
Ole
  • 41,793
  • 59
  • 191
  • 359

2 Answers2

2

Found a similar solution here (Gson: JsonSyntaxException on date), and tweaked it slightly:

class JsonDateDeserializer
    implements JsonDeserializer<Date> {

    public Date deserialize(JsonElement json,
                            Type date,
                            JsonDeserializationContext context)
        throws JsonParseException {
        String stringDate = json.getAsJsonPrimitive().getAsString();
        return new Date(Long.parseLong(stringDate));
    }
}

Gson gson =
    new GsonBuilder().registerTypeAdapter(Date.class,
                                          new JsonDateDeserializer())
        .create();

This works. It would be great if this was the default in GSON :).

Community
  • 1
  • 1
Ole
  • 41,793
  • 59
  • 191
  • 359
0

You can write a simple Type Adapter and register it either with the GsonBuilder instance, or annotate with @JsonAdapter in the Contact class itself. Note that you should serialize dates as long strings because long is NOT a valid JSON type and may get trimmed to an int (which will certainly fail for most dates).

Here is how the adapter will look like:

public class LongDateTypeAdapter extends TypeAdapter<Date> {
  @Override public void write(JsonWriter out, Date value) throws IOException {
    if (value == null) {
      out.nullValue();
    } else {
      out.value(String.valueOf(value.getTime()));
    }
  }
  @Override public Date read(JsonReader in) throws IOException {
    switch (in.peek()) {
    case NULL: return null;
    case STRING: 
      try {
        return new Date(Long.parseLong(in.nextString()));
      } catch (NumberFormatException e) {
        throw new JsonSyntaxException(e);
      }
    default: throw new JsonSyntaxException("invalid date" + in.getPath());
    }
  }
}

You can see the source code at: https://github.com/google-gson/typeadapters/blob/master/common/src/main/java/LongDateTypeAdapter.java

Here are the tests illustrating how to use it: https://github.com/google-gson/typeadapters/blob/master/common/src/test/java/LongDateTypeAdapterTest.java

inder
  • 1,774
  • 1
  • 15
  • 15
  • Hello @inder123 Thank you for pointing out the alternate solutions. Could we add a simple option to the builder for searialization that specifies one of the three standard forms that Spring Boot lists in the exception? (\"yyyy-MM-dd'T'HH:mm:ss.SSSZ\" \"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'\" \"EEE, dd MMM yyyy HH:mm:ss zzz\" \"yyyy-MM-dd\")) Also it would be great if GSON had a more intelligent deserialization that mirrors that of Spring Boot Marshalling and perhaps incorporates formats from other frameworks as well. – Ole Jun 10 '15 at 16:18
  • @user1684269 You should use GsonBuilder.setDateFormat() with the patterns of your choice. – inder Jun 11 '15 at 17:18