Java 如何使用 Jackson 反序列化以秒为单位的时间戳?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20635698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 03:16:10  来源:igfitidea点击:

How do I deserialize timestamps that are in seconds with Hymanson?

javajsontimestampHymansonunix-timestamp

提问by Drew Stephens

I've got some JSON that has timestamps in seconds (i.e. a Unix timestamp):

我有一些以秒为单位的时间戳(即 Unix 时间戳):

{"foo":"bar","timestamp":1386280997}

Asking Hymanson to deserialize this into an object with a DateTime field for the timestamp results in 1970-01-17T01:11:25.983Z, a time shortly after the epoch because Hymanson is assuming it to be in milliseconds. Aside from ripping apart the JSON and adding some zeros, how might I get Hymanson to understand the secondstimestamp?

要求 Hymanson 将其反序列化为一个带有 DateTime 字段作为时间戳的对象,结果是在1970-01-17T01:11:25.983Z纪元之后不久,因为 Hymanson 假设它以毫秒为单位。除了撕开 JSON 并添加一些零之外,我如何让 Hymanson 理解时间戳?

采纳答案by Drew Stephens

I wrote a custom deserializerto handle timestamps in seconds (Groovy syntax).

我编写了一个自定义解串器来以秒为单位处理时间戳(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
        }
    }
}

And then I annotated my POGO to use that for the timestamp:

然后我注释了我的 POGO 以将其用于时间戳:

class TimestampThing {
    @JsonDeserialize(using = UnixTimestampDeserializer.class)
    DateTime timestamp

    @JsonCreator
    public TimestampThing(@JsonProperty('timestamp') DateTime timestamp) {
        this.timestamp = timestamp
    }
}

回答by sherpya

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="s")
public Date timestamp;

edit: vivek-kothari suggestion

编辑:vivek-kothari 建议

@JsonFormat(shape=JsonFormat.Shape.NUMBER, pattern="s")
public Timestamp timestamp;

回答by Priidu Neemre

A very similar approach to that of @DrewStephens's which uses the Java SE TimeUnitAPI (introduced in JDK1.5) instead of plain String concatenation and is thus (arguably) a little bit cleaner and more expressive:

一种与@DrewStephens 的方法非常相似的方法,它使用 Java SE TimeUnitAPI(在 中引入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)));
    }
}

Specifying your custom deserializer (UnixTimestampDeserializer) on the affected Datefield(s):

UnixTimestampDeserializer在受影响的Date字段上指定您的自定义解串器 ( ):

@JsonDeserialize(using = UnixTimestampDeserializer.class)
private Date updatedAt;

回答by svarog

I had this exact issue, except my ZonedDateTime objects got turned to unix-timestamps (seconds) and I needed them in milliseconds (to initialize JS Date objects on the browser).

我有这个确切的问题,除了我的 ZonedDateTime 对象变成了 unix-timestamps(秒)并且我需要它们以毫秒为单位(在浏览器上初始化 JS Date 对象)。

Implementing a custom serializer/deserializer looked like too much work for something that should be pretty straightforward, so I looked elsewhere and found that I can just configure the object mapper for the desired result.

实现自定义序列化器/反序列化器对于应该非常简单的事情来说看起来工作量太大,所以我查看了其他地方,发现我可以只为所需的结果配置对象映射器。

Because my application already overrides the default ObjectMapper provided by Jersey, I just had to disable SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS.

因为我的应用程序已经覆盖了 Jersey 提供的默认 ObjectMapper,所以我只需要禁用SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS.

Here's my code

这是我的代码

@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;
    }
}

And that's it

就是这样