Custom `LocalDate` deserializer not being used with 2.11, jsr-310 datatype module
See original GitHub issueDear Jackson team,
It seems that as of Jackson 2.11 my custom (date) deserializer is no longer being used by the object mapper. I’ve tried various ways of registering the deserializer but none seem to work. In the previous version (2.10.4) this was not a problem.
Strangely the JSR310 LocalDateDeserializer is being detected and registered automatically from the classpath, skipping the deserializer in my custom module.
Example:
public class CustomLocalDateDeserializerTest {
@Test
public void parse_dates_shouldSucceed() throws JsonProcessingException {
SimpleModule module = new SimpleModule();
module.addDeserializer(LocalDate.class, new CustomLocalDateDeserializer());
ObjectMapper objectMapper = JsonMapper.builder()
.addModule(module)
.build();
final String json = "{\"endDate\":1567202400000,\"startDate\":1564610400000}";
Dates dates = objectMapper.readValue(json, Dates.class);
assertNotNull(dates);
assertEquals(LocalDate.of(2019, 8, 1), dates.getStartDate());
assertEquals(LocalDate.of(2019, 8, 31), dates.getEndDate());
}
@Getter
@Setter
public static class Dates {
private LocalDate startDate;
private LocalDate endDate;
}
}
@Slf4j
public final class CustomLocalDateDeserializer extends com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer {
public CustomLocalDateDeserializer() {
super(DateTimeFormatter.ISO_LOCAL_DATE);
}
@Override
public LocalDate deserialize(JsonParser parser, DeserializationContext context) throws IOException {
if (parser.hasToken(JsonToken.VALUE_NUMBER_INT)) {
long value = parser.getLongValue();
if (!isValidEpochDay(value)) {
return toLocalDate(value);
}
}
return super.deserialize(parser, context);
}
private static boolean isValidEpochDay(long value) {
try {
ChronoField.EPOCH_DAY.checkValidValue(value);
} catch (DateTimeException ex) {
log.trace("Date value {} is not a valid epoch day value.", value);
return false;
}
return true;
}
private static LocalDate toLocalDate(Long millis) {
Instant instant = Instant.ofEpochMilli(millis);
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
return LocalDate.of(ldt.getYear(), ldt.getMonth(), ldt.getDayOfMonth());
}
}
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:6 (4 by maintainers)
Top Results From Across the Web
Jackson module not registered after update from Spring Boot ...
This problem occurs because JSON doesn't natively have a date format, so it represents dates as String. The String representation of a date ......
Read more >Jackson Date - Baeldung
The @JsonDeserialize annotation is used to specify a custom deserializer to unmarshal the JSON object. Similarly, @JsonSerialize indicates a ...
Read more >Java 8 date/time type not supported by default - You.com
Implement a custom Deserializer. Let's walk through these options. Parse the Timestamp inside the Constructor. We can declare all-args constructor inside the ...
Read more >JavaTimeModule (Jackson datatype: JSR310 2.11.0 API)
Class that registers capability of serializing java.time objects with the Jackson core. ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new ...
Read more >How to Handle Java 8 Dates and Time with Jackson in Spring ...
By Default, it does not handle the new Java 8 date and time classes correctly ... When we use a LocalDateTime, it will...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Pardon, I’ve found the probleem and it’s indeed not a bug. Between 2.10.4 en 2.11.0 the deserializer now uses the following method:
Which creates a new deserializer, replacing my custom deserializer. I’ve solved the problem by using composition over inheritance:
Ok, glad you figure out the issue. Sub-classing is quite fragile, unfortunately, and composition is encouraged, for this reason.