
在与外部rest服务交互时,我们经常会遇到日期时间字段以epoch毫秒(自1970年1月1日00:00:00 utc以来的毫秒数)的形式传输。例如,一个json响应可能包含如下结构:
{
"name": "anything",
"creation_date": 1666190973000,
"created_by": "anyone"
}而我们的Java应用中,通常希望将creation_date这样的字段直接映射到Java 8的LocalDateTime或LocalDate类型:
public class MyLocalApplicationClass {
private String name;
private LocalDateTime creationDate; // 期望的目标类型
private String createdBy;
// ... getters, setters ...
}然而,直接尝试将Epoch毫秒时间戳反序列化为LocalDateTime或LocalDate时,Jackson默认行为可能导致以下错误:
为了解决这些问题,我们需要采取特定的策略来指导Jackson正确地进行类型转换。
以下是几种处理Jackson反序列化Epoch毫秒时间戳到Java 8日期时间类型的有效方法。
立即学习“Java免费学习笔记(深入)”;
这种方法的核心思想是让Jackson将时间戳字段作为原始的long类型传递给数据类的构造函数,然后在构造函数内部手动将其转换为LocalDateTime。
实现步骤:
示例代码:
import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
public class MyLocalApplicationClass {
private String name;
private LocalDateTime creationDate;
private String createdBy;
// 全参数构造函数,用于Jackson反序列化
public MyLocalApplicationClass(@JsonProperty("name") String name,
@JsonProperty("creation_date") long creationDate,
@JsonProperty("created_by") String createdBy) {
this.name = name;
this.createdBy = createdBy;
// 将Epoch毫秒时间戳转换为UTC时区的LocalDateTime
this.creationDate = Instant
.ofEpochMilli(creationDate)
.atZone(ZoneOffset.UTC) // 假设时间戳是UTC时间
.toLocalDateTime();
}
// ... getters and other methods ...
public String getName() { return name; }
public LocalDateTime getCreationDate() { return creationDate; }
public String getCreatedBy() { return createdBy; }
@Override
public String toString() {
return "MyLocalApplicationClass{" +
"name='" + name + '\'' +
", creationDate=" + creationDate +
", createdBy='" + createdBy + '\'' +
'}';
}
}优点:
缺点:
对于更通用的场景,我们可以配置Jackson的ObjectMapper来自动处理Epoch毫秒时间戳。这种方法通常涉及将目标字段类型更改为Instant,并配置Jackson的行为。
核心思想:
实现步骤(Spring Boot环境):
A. 配置ObjectMapper Bean:
在Spring Boot应用中,可以通过配置类来注册JavaTimeModule并设置反序列化特性。
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
@Configuration
public class JsonConfig {
@Bean
public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() {
return new Jackson2ObjectMapperBuilder();
}
@Bean
public ObjectMapper objectMapper() {
return jackson2ObjectMapperBuilder()
.build()
.registerModule(new JavaTimeModule()) // 注册Java 8日期时间模块
// 告知Jackson时间戳是毫秒而不是纳秒
.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false);
}
}B. 更新数据类:
将creationDate字段的类型更改为Instant。如果JSON字段名与Java字段名不匹配,仍需使用@JsonProperty。
import com.fasterxml.jackson.annotation.JsonProperty;
import java.time.Instant;
public class MyLocalApplicationClass {
private String name;
@JsonProperty("creation_date") // 如果JSON字段名不同
private Instant creationDate; // 更改为Instant类型
@JsonProperty("created_by")
private String createdBy;
// ... getters, setters, and other methods ...
public String getName() { return name; }
public Instant getCreationDate() { return creationDate; } // 返回Instant
public LocalDateTime getCreationLocalDateTime() { // 如果需要LocalDateTime,可以提供一个转换方法
return creationDate != null ? creationDate.atZone(ZoneOffset.UTC).toLocalDateTime() : null;
}
public String getCreatedBy() { return createdBy; }
@Override
public String toString() {
return "MyLocalApplicationClass{" +
"name='" + name + '\'' +
", creationDate=" + creationDate + // Instant的toString()方法
", createdBy='" + createdBy + '\'' +
'}';
}
}C. 简化全局配置(Spring Boot推荐):
在Spring Boot中,JacksonAutoConfiguration会自动检测并注册所有已知的Jackson模块。因此,我们通常不需要手动声明ObjectMapper或Jackson2ObjectMapperBuilder Bean。只需在application.properties或application.yml中进行配置即可。
application.properties配置:
spring.jackson.deserialization.READ_DATE_TIMESTAMPS_AS_NANOSECONDS=false
application.yml配置:
spring:
jackson:
deserialization:
read-date-timestamps-as-nanoseconds: false使用这种方式,你只需确保jackson-datatype-jsr310依赖已添加到项目中,并且数据类中的日期时间字段类型为Instant。
优点:
缺点:
当上述方法不能满足特定需求(例如,你必须将Epoch毫秒直接反序列化为LocalDateTime,并且需要更精细的控制或特定的时区逻辑),可以实现一个自定义的Jackson反序列化器。
实现步骤:
示例代码:
A. 自定义反序列化器:
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
public class DateTimeDeserializer extends StdDeserializer<LocalDateTime> {
public DateTimeDeserializer() {
super(LocalDateTime.class);
}
@Override
public LocalDateTime deserialize(JsonParser p,
DeserializationContext ctxt) throws IOException, JacksonException {
// 读取JSON节点
JsonNode node = p.getCodec().readTree(p);
// 获取长整型的时间戳值
long timestamp = node.longValue();
// 将Epoch毫秒时间戳转换为UTC时区的LocalDateTime
return Instant
.ofEpochMilli(timestamp)
.atZone(ZoneOffset.UTC) // 假设时间戳是UTC时间
.toLocalDateTime();
}
}B. 应用到数据类字段:
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import java.time.LocalDateTime;
public class MyLocalApplicationClass {
private String name;
@JsonDeserialize(using = DateTimeDeserializer.class) // 应用自定义反序列化器
@JsonProperty("creation_date")
private LocalDateTime creationDate; // 字段类型保持为LocalDateTime
@JsonProperty("created_by")
private String createdBy;
// ... getters, setters, and other methods ...
public String getName() { return name; }
public LocalDateTime getCreationDate() { return creationDate; }
public String getCreatedBy() { return createdBy; }
@Override
public String toString() {
return "MyLocalApplicationClass{" +
"name='" + name + '\'' +
", creationDate=" + creationDate +
", createdBy='" + createdBy + '\'' +
'}';
}
}优点:
缺点:
在处理Jackson反序列化Epoch毫秒时间戳到Java 8日期时间类型时,我们有多种策略可供选择:
选择哪种方法取决于你的项目需求、对代码复杂度的接受程度以及是否使用Spring Boot等框架。通常,对于Spring Boot项目,配置application.properties并使用Instant类型是最优雅和推荐的解决方案。
以上就是Jackson处理REST响应中时间戳到Java 8日期时间类型的实践指南的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号