Search code examples
javajsongson

How can GSON be configured to recognize ISO date fields as parse them as Date objects?


This code:

Map<String, Object> map = new HashMap<>();
map.put("now", new Date());

Gson gson = new GsonBuilder()
        .setDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
        .create();
String json = gson.toJson(map);
System.out.println(json);

produces something like {"now":"2023-03-11T12:34:56.789Z"}

Contrarily, undoing the action like this:

Map<String, Object> map = gson.fromJson(json, new TypeToken<Map<String, Object>>(){}.getType());

fails to produce the input data - instead giving output like {"now":"2023-03-11T12:34:56.789Z"}.

The date string stays a string instead of being converted back to a Date object.

How may the string be parsed back into a Map so that GSON recognises the date string and parses it back to a Date object.

The regex pattern "\\d{1,4}-\\d{2}-\\d{2}T\\d{2}\\:\\d{2}\\:\\d{2}\\.\\d{3}Z" roughly correlates to the date pattern.

Basically, I need to tell GSON by configuration: If the string matches regex part (DATE_PATTERN) deserialize it as a date.

Note: I am aware that deserializing to a class with date field would work properly since the field type gives GSON a hint. I need GSON to determine the target type simply based on the format of the string.


Solution

  • This is not possible; Gson does not allow overwriting the default type adapter factory for Object.

    There are probably the following alternatives:

    • Manually process the Map after it was deserilized with Gson and convert the values
    • Have a model class with Object as field type (if directly specifying Date is not possible for some reason), and then place a @JsonAdapter annotation on the field specifying your custom adapter factory
    • Specify one of the general purpose interfaces implemented by Date (Serializable, Cloneable or Comparable) as value type of the map, e.g. Map<String, Serializable>, and then register a type adapter factory for that interface. This is possibly not a very clean solution and of course only works if the other deserialized values of the map implement that interface as well.
    • Register a custom type adapter factory for Map which performs conversion of the values