I found a way to do it without writing a custom deserializer, but it'll require some modifications.
First, the LocalDateDeserializer
accepts a custom DateTimeFormatter
. So, we need to create a formatter that accepts an epoch millis. I did this by joining the INSTANT_SECONS
and MILLI_OF_SECOND
fields:
// formatter that accepts an epoch millis value
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
// epoch seconds
.appendValue(ChronoField.INSTANT_SECONDS, 1, 19, SignStyle.NEVER)
// milliseconds
.appendValue(ChronoField.MILLI_OF_SECOND, 3)
// create formatter, using UTC as timezone
.toFormatter().withZone(ZoneOffset.UTC);
I also set the formatter with UTC zone, so it won't be affected by timezones and DST changes.
Then, I've created the deserializer and registered in my ObjectMapper
:
ObjectMapper mapper = new ObjectMapper();
JavaTimeModule module = new JavaTimeModule();
// add the LocalDateDeserializer with the custom formatter
module.addDeserializer(LocalDate.class, new LocalDateDeserializer(formatter));
mapper.registerModule(module);
I also had to remove the annotation from the birthday
field (because the annotation seems to override the module configuration):
public class FbProfile {
long id;
// remove @JsonDeserialize annotation
LocalDate birthday;
}
And now the big issue: as the DateTimeFormatter
accepts only String
as input, and the JSON contains a number in birthday
field, I had to change the JSON:
{
"id" : "1",
"birthday" : "401280850089"
}
Note that I changed birthday
to a String
(put the value between quotes).
With this, the LocalDate
is read from JSON correctly:
FbProfile value = mapper.readValue(json, FbProfile.class);
System.out.println(value.getBirthday()); // 1982-09-19
Notes:
- I couldn't find a way to pass the number directly to the formatter (as it takes only
String
as input), so I had to change the number to be a String
. If you don't want to do that, then you'll have to write a custom converter anyway.
- You can replace
ZoneOffset.UTC
with any timezone you want (even ZoneId.systemDefault()
), it'll depend on what your application needs. But as told in @Ole V.V.'s comment, the timezone might cause the date to change.
Date
class. The only thing it gives you that modern classes don’t is trouble. If you want to try other classes thanLocalDate
,Instant
is the obvious choice. – Landan@JsonDeserialize(using = LocalDateDeserializer.class)
but it doesn't work with epoch. Nevertheless thank you for the hint. – Create