Как удалить десериализацию временных меток, которые находятся в секундах с Джексоном?

У меня есть 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;
    }
}

И что это