Я нашел способ сделать это без написания специального десериализатора, но он потребует некоторых изменений.
Во-первых, LocalDateDeserializer
принимает пользовательский DateTimeFormatter
. Итак, нам нужно создать средство форматирования, которое принимает миллисекунды эпох. Я сделал это, соединив поля INSTANT_SECONS
и MILLI_OF_SECOND
:
// 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);
Я также установил форматировщик с зоной UTC, чтобы на него не повлияли изменения часовых поясов и летнего времени.
Затем я создал десериализатор и зарегистрировался в моем 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);
Мне также пришлось удалить аннотацию из поля birthday
(потому что аннотация, похоже, переопределяет конфигурацию модуля):
public class FbProfile {
long id;
// remove @JsonDeserialize annotation
LocalDate birthday;
}
А теперь большая проблема: поскольку DateTimeFormatter
принимает в качестве входных данных только String
, а JSON содержит число в поле birthday
, мне пришлось изменить JSON:
{
"id" : "1",
"birthday" : "401280850089"
}
Обратите внимание, что я изменил birthday
на String
(поместите значение в кавычки).
При этом LocalDate
правильно читается из JSON:
FbProfile value = mapper.readValue(json, FbProfile.class);
System.out.println(value.getBirthday()); // 1982-09-19
Примечания:
- Я не смог найти способ передать номер непосредственно в форматтер (поскольку он принимает только
String
в качестве входных данных), поэтому мне пришлось изменить число на String
. Если вы не хотите этого делать, вам все равно придется написать собственный конвертер.
- Вы можете заменить
ZoneOffset.UTC
любым часовым поясом (даже ZoneId.systemDefault()
), это будет зависеть от того, что нужно вашему приложению. Но, как сказано в комментарии @Ole VV, часовой пояс может вызвать изменение даты.
person
Community
schedule
08.06.2017
Date
. Единственное, что дает вам то, чего не делают современные классы, - это неприятности. Если вы хотите попробовать другие классы, кромеLocalDate
,Instant
- очевидный выбор. - person Ole V.V.   schedule 08.06.2017@JsonDeserialize(using = LocalDateDeserializer.class)
, но она не работает с эпохой. Тем не менее спасибо за подсказку. - person kpater87   schedule 08.06.2017