Jackson Mapper转换Unix时间戳为日期结果异常求助
问题分析与解决方案
这绝对不是Jackson的问题——我之前也碰到过一模一样的坑!咱们来拆解一下:
为什么会出现这个错误?
Jackson默认把Unix时间戳当成毫秒级来解析,但你的JSON里的时间戳应该是秒级的。举个例子:
- 你要的正确日期
Wednesday, February 7, 2018 9:55:33 PM对应的秒级时间戳是1518030933 - 如果Jackson把这个数值当成毫秒数,那它对应的就是
1518030933毫秒,换算成日期就是Sun Jan 18 13:40:40 UTC 1970——正好和你得到的结果一致!
说白了就是配置和数据格式不匹配,不是Jackson的bug。
解决方案
根据你用的日期类型(旧的java.util.Date或者Java 8的LocalDateTime等),有两种处理方式:
情况1:使用java.util.Date
方式A:给单个字段加注解
直接在日期字段上指定反序列化规则,把秒级时间戳转成Date:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; import java.util.Date; // 自定义秒级时间戳反序列化器 class UnixSecondsDateDeserializer extends StdDeserializer<Date> { public UnixSecondsDateDeserializer() { super(Date.class); } @Override public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { long timestamp = p.getLongValue(); return new Date(timestamp * 1000); // 秒转毫秒 } } // 在实体类字段上使用 public class YourEntity { @JsonDeserialize(using = UnixSecondsDateDeserializer.class) private Date targetDate; // getter、setter省略 }
方式B:全局配置ObjectMapper
如果所有日期字段都是秒级时间戳,可以全局配置,不用每个字段加注解:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.module.SimpleModule; ObjectMapper objectMapper = new ObjectMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(Date.class, new UnixSecondsDateDeserializer()); objectMapper.registerModule(module);
情况2:使用Java 8日期API(如LocalDateTime)
方式A:字段级注解
自定义反序列化器处理秒级时间戳转LocalDateTime:
import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import java.io.IOException; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; class UnixSecondsLocalDateTimeDeserializer extends StdDeserializer<LocalDateTime> { public UnixSecondsLocalDateTimeDeserializer() { super(LocalDateTime.class); } @Override public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { long timestamp = p.getLongValue(); // 注意时区,根据你的实际需求调整,比如换成ZoneId.of("Asia/Shanghai") return LocalDateTime.ofInstant(Instant.ofEpochSecond(timestamp), ZoneId.of("UTC")); } } // 实体类字段使用 public class YourEntity { @JsonDeserialize(using = UnixSecondsLocalDateTimeDeserializer.class) private LocalDateTime targetDate; // getter、setter省略 }
方式B:全局配置
注册JavaTime模块并替换默认反序列化器:
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; ObjectMapper objectMapper = new ObjectMapper(); JavaTimeModule module = new JavaTimeModule(); module.addDeserializer(LocalDateTime.class, new UnixSecondsLocalDateTimeDeserializer()); objectMapper.registerModule(module);
额外提醒
别忘了根据你的业务场景调整时区!比如你给出的正确日期是晚上9点多,可能对应的是UTC+8或者其他时区,在代码里把ZoneId改成对应的时区即可。
内容的提问来源于stack exchange,提问作者DawnZHANG
相关产品推荐
相关产品推荐

