Как удалить десериализацию временных меток, которые находятся в секундах с Джексоном?
У меня есть JSON, у которого есть отметки времени в секундах (т.е. временная метка Unix):
{"foo":"bar","timestamp":1386280997}
Попросив Джексона десериализовать это в объект с полем DateTime для timestamp, результат 1970-01-17T01:11:25.983Z
, время вскоре после эпохи, потому что Джексон предполагает, что он будет в миллисекундах. Помимо разрыва JSON и добавления некоторых нулей, как я могу заставить Джексона понять временную метку секунд?
Ответы
Ответ 1
Я написал пользовательский deserializer для обработки временных меток в секундах (синтаксис Groovy).
class UnixTimestampDeserializer extends JsonDeserializer<DateTime> {
Logger logger = LoggerFactory.getLogger(UnixTimestampDeserializer.class)
@Override
DateTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
String timestamp = jp.getText().trim()
try {
return new DateTime(Long.valueOf(timestamp + '000'))
} catch (NumberFormatException e) {
logger.warn('Unable to deserialize timestamp: ' + timestamp, e)
return null
}
}
}
И затем я аннотировал мой POGO, чтобы использовать его для метки времени:
class TimestampThing {
@JsonDeserialize(using = UnixTimestampDeserializer.class)
DateTime timestamp
@JsonCreator
public TimestampThing(@JsonProperty('timestamp') DateTime timestamp) {
this.timestamp = timestamp
}
}
Ответ 2
@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="s")
public Date timestamp;
изменить: предложение vivek-kothari
@JsonFormat(shape=JsonFormat.Shape.NUMBER, pattern="s")
public Timestamp timestamp;
Ответ 3
Очень похожий подход к методу @DrewStephens, который использует API-интерфейс Java SE TimeUnit
(введенный в JDK1.5
) вместо простой конкатенации строк и, следовательно, (возможно) немного чище и выразительнее:
public class UnixTimestampDeserializer extends JsonDeserializer<Date> {
@Override
public Date deserialize(JsonParser parser, DeserializationContext context)
throws IOException, JsonProcessingException {
String unixTimestamp = parser.getText().trim();
return new Date(TimeUnit.SECONDS.toMillis(Long.valueOf(unixTimestamp)));
}
}
Указание настраиваемого десериализатора (UnixTimestampDeserializer
) в затронутых (-ях) областях Date
:
@JsonDeserialize(using = UnixTimestampDeserializer.class)
private Date updatedAt;
Ответ 4
У меня была именно эта проблема, за исключением того, что мои объекты ZonedDateTime превратились в метки времени unix (секунды), и мне они нужны в миллисекундах (для инициализации объектов JS Date в браузере).
Реализация собственного сериализатора/десериализатора выглядела как слишком большая работа для чего-то, что должно быть довольно простым, поэтому я посмотрел в другом месте и обнаружил, что могу просто настроить объектный маппер для желаемого результата.
Поскольку мое приложение уже переопределяет ObjectMapper по умолчанию, предоставленный Джерси, мне просто нужно было отключить SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS
.
Вот мой код
@Provider
public class RPObjectMapperProvider implements ContextResolver<ObjectMapper> {
final ObjectMapper defaultObjectMapper;
public RPObjectMapperProvider() {
defaultObjectMapper = new ObjectMapper();
// this turned ZonedDateTime objects to proper seconds timestamps
defaultObjectMapper.enable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// disable to serialize dates for millis timestamps
defaultObjectMapper.disable(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS);
// using Java8 date time classes
defaultObjectMapper.registerModule(new JavaTimeModule());
}
@Override
public ObjectMapper getContext(Class<?> type) {
return defaultObjectMapper;
}
}
И что это