使用 Jackson JSR310 模块反序列化 LocalDateTime
Posted
技术标签:
【中文标题】使用 Jackson JSR310 模块反序列化 LocalDateTime【英文标题】:Deserializing LocalDateTime with Jackson JSR310 module 【发布时间】:2015-06-16 18:31:42 【问题描述】:我正在使用the Jackson Datatype JSR310 page 描述的库,但我仍然难以让它工作。
我已经配置了以下bean:
@Bean
@Primary
public ObjectMapper objectMapper()
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JSR310Module());
return mapper;
当我调用我的 REST API 时,日期格式输出为 yyyy-MM-dd'T'HH:ss.SSSSSS
,例如2015-04-11T00:10:38.905847
。这可以由我的 AngularJS 代码处理。
当我想向 REST API 提交内容时,日期会发布为 yyyy-MM-dd'T'HH:mm:ss.SSS'Z'
,例如2015-04-09T08:30:00.000Z
杰克逊最后一直在抱怨“Z”。如果我查看文档中的LocalDateTimeDeserializer
,它使用DateTimeFormatter.ISO_LOCAL_DATE_TIME
,它归结为ISO_LOCAL_DATE'T'ISO_LOCAL_TIME
,并提到它没有覆盖区域。
所以我想我应该在我正在创建的ObjectMapper
上设置DateFormat
:
@Bean
@Primary
public ObjectMapper objectMapper()
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JSR310Module());
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
return mapper;
但这无济于事。我将其更改为yyyy-MM-dd
之类的简单名称,但序列化日期仍为以前的格式,反序列化也不受影响。
我在这里做错了什么才能使其正常工作?据我所知,我的 javascript 代码中的日期格式是 ISO 8601 格式...
【问题讨论】:
我认为如果你切换到 ZoneDateTime 可能会起作用。 @AlexeyGavrilov,这确实有效,谢谢。如果您将其作为答案提交,我会将其标记为正确。仍然觉得奇怪的是,在 objectmapper 本身上设置 dateFormat 对序列化/反序列化绝对没有影响,但使用 ZonedDateTime 很容易:-) ObjectMapper 的 DateFormat 仅用于内置 java.util.Date 支持,我猜。将带有时区指示的值传递给 LocalDateTime 是一种气味- Instant 或 OffsetDateTime(甚至 ZonedDateTime)更适用。 【参考方案1】:Hibernate 4、Spring 4 - REST WS、客户端 - Spring Boot 1.5.2。在我的例子中,我在实体 ZonedDateTime 类中使用了将 Timestamp 映射到数据库中。 Hibernate 和 Spring Boot REST 工作正常。我只能将库添加到 pom 文件中:
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>$jackson.version</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-jsr310 -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>$jackson.version</version>
</dependency>
所以我想,该转换器也是在 Spring 中为 LocalDateTime 实现的。jackson.version 是最新的。
【讨论】:
OP 提到他们已经在使用 Jackson JSR 310 模块(否则JSR310Module
类将不可用)。
是的,当然,但我没有更多的事情可做。不需要对象映射器,也不需要注册模块。【参考方案2】:
不必编写自己的序列化程序。使用默认格式就足够了,但是使用另一种格式(time_zone
格式)创建一个实例,以便剪切超出部分:
new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME)
就我而言,我有一个像这样的contextResolver
可以在配置级别实现:
@Service
@Provider
public class ObjectMapperContextResolver implements ContextResolver<ObjectMapper>
private final ObjectMapper mapper;
public ObjectMapperContextResolver()
mapper = new ObjectMapper();
JavaTimeModule javaTimeModule=new JavaTimeModule();
// Hack time module to allow 'Z' at the end of string (i.e. javascript json's)
javaTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(DateTimeFormatter.ISO_DATE_TIME));
mapper.registerModule(javaTimeModule);
mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
@Override
public ObjectMapper getContext(Class<?> type)
return mapper;
【讨论】:
我相信这个答案更合适,因为它演示了如何设置ObjectMapper
以自动正确地处理反序列化。如果您不手动使用 ObjectMapper
intsance 读取传入的字符串,而是通过诸如 RestTemplate
之类的东西来工作,则这是必需的
嗯。尝试此操作时出现此异常: java.lang.IllegalAccessError: 试图访问方法 com.fasterxml.jackson.databind.ser.std.StdSerializer.<init>(Ljava/lang/Class;& #41;来自 com.fasterxml.jackson.datatype.jsr310.JavaTimeModule 类的 V
你能看看***.com/questions/44918021/…吗?是不是很相似?如果可能请回答。【参考方案3】:
目前LocalDateTimeDeserializer
似乎不遵守为对象映射器设置的日期格式。
要使其正常工作,您可以覆盖 LocalDateTimeDeserializer
或切换到使用 ZoneDateTime
来处理末尾的“Z”字符。
这是一个例子:
public class Java8DateFormat
public static void main(String[] args) throws IOException
final ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JSR310Module());
// mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"));
final String date = mapper.writeValueAsString(new Date());
System.out.println(date);
System.out.println(mapper.readValue(date, ZonedDateTime.class));
输出:
"2015-04-11T18:24:47.815Z"
2015-04-11T18:24:47.815Z[GMT]
【讨论】:
请注意JSR310Module
已被弃用,请改用JavaTimeModule
。
您可以在这里找到新模块:github.com/FasterXML/jackson-modules-java8。以上是关于使用 Jackson JSR310 模块反序列化 LocalDateTime的主要内容,如果未能解决你的问题,请参考以下文章
Spring Boot Jackson JSR-310 - ZonedDateTime 总是时间戳
在春季使用 JSR310 java.time 时将日期、即时序列化为 ISO 8601
如何正确地在Spring Data JPA和Jackson中用上Java 8的时间相关API(即JSR 310也即java.time包下的众神器)