如何将带UTC偏移量的时间戳反序列化为java.time.Instant
如何将带UTC偏移量的时间戳反序列化为
java.time.Instant 你遇到的问题是Jackson默认的JavaTimeModule无法解析2023-05-04T19:40:07.000+0200这种格式的时间字符串到Instant——原因是该格式的偏移部分(+0200)不带冒号,不符合Instant默认支持的ISO-8601标准格式(标准偏移格式为+02:00)。下面提供几种可行的解决方案:
方案一:用@JsonFormat注解指定自定义格式
直接在实体类的Instant字段上添加注解,明确匹配目标字符串的格式:
import com.fasterxml.jackson.annotation.JsonFormat; import java.time.Instant; static class MyClass { // 省略构造方法、getter、setter @JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone = "UTC") private Instant time; }
这里的pattern中,Z对应不带冒号的UTC偏移格式(如+0200),timezone确保最终转换为UTC时区的Instant。
方案二:给ObjectMapper配置自定义反序列化器
如果不想修改实体类,可以通过给ObjectMapper添加自定义反序列化器来适配格式:
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import org.junit.jupiter.api.Test; import java.time.Instant; import java.time.OffsetDateTime; import java.time.format.DateTimeFormatter; public class MyInstantTest { @Test void test1() throws JsonProcessingException { JavaTimeModule javaTimeModule = new JavaTimeModule(); // 添加自定义Instant反序列化器 javaTimeModule.addDeserializer(Instant.class, new StdDeserializer<Instant>(Instant.class) { @Override public Instant deserialize(com.fasterxml.jackson.core.JsonParser p, com.fasterxml.jackson.databind.DeserializationContext ctxt) throws java.io.IOException { String timeStr = p.getText(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"); OffsetDateTime offsetDateTime = OffsetDateTime.parse(timeStr, formatter); return offsetDateTime.toInstant(); } }); final ObjectMapper objectMapper = new ObjectMapper() .registerModule(javaTimeModule) .disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS) .disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS); final MyClass deserializedObject = objectMapper.readValue("{\"time\":\"2023-05-04T19:40:07.000+0200\"}", MyClass.class); System.out.println("deserializedObject.getTime() = " + deserializedObject.getTime()); } static class MyClass { // 原实体类代码不变 MyClass() {} MyClass(Instant time) { this.time = time; } public Instant getTime() { return time; } public void setTime(final Instant time) { this.time = time; } private Instant time; } }
逻辑是先把字符串解析为支持带偏移格式的OffsetDateTime,再转换为Instant。
方案三:临时用OffsetDateTime中转
如果允许修改实体类字段类型,可以先将字段定义为OffsetDateTime,在getter中转换为Instant:
import java.time.Instant; import java.time.OffsetDateTime; static class MyClass { private OffsetDateTime time; // 构造方法调整 MyClass() {} MyClass(Instant time) { this.time = OffsetDateTime.ofInstant(time, java.time.ZoneOffset.UTC); } public Instant getTime() { return time.toInstant(); } public void setTime(final OffsetDateTime time) { this.time = time; } }
这种方式无需额外配置Jackson,因为JavaTimeModule默认支持OffsetDateTime解析(包括+0200格式)。
内容的提问来源于stack exchange,提问作者Saif
相关产品推荐
相关产品推荐

