gpt4 book ai didi

java - jackson jsr310 中缺少 ZonedDateTimeDeserializer

转载 作者:搜寻专家 更新时间:2023-11-01 02:58:22 32 4
gpt4 key购买 nike

我正在解析 ZonedDateTime 使用这样的:

 @JsonSerialize(using = ZonedDateTimeSerializer.class)
private ZonedDateTime expirationDateTime;

我需要能够正确反序列化这个日期。但是,jackson 没有为此提供反序列化器:

com.fasterxml.jackson.datatype.jsr310.deser

它丢失的原因是什么?最常见的解决方法是什么?

已更新:这是我的场景:

我这样创建 ZonedDateTime:

ZonedDateTime.of(2017, 1, 1, 1, 1, 1, 1, ZoneOffset.UTC)

然后我像这样序列化包含日期的对象:

public static String toJSON(Object o) {
ObjectMapper objectMapper = new ObjectMapper();
StringWriter sWriter = new StringWriter();
try {
JsonGenerator jsonGenerator = objectMapper.getJsonFactory().createJsonGenerator(sWriter);
objectMapper.writeValue(jsonGenerator, o);
return sWriter.toString();
} catch (IOException e) {
throw new IllegalStateException(e);
}
}

当我尝试将它发送到 Spring MVC Controller 时:

    mockMvc.perform(post("/endpoint/")
.content(toJSON(myObject))
.contentType(APPLICATION_JSON))
.andExpect(status().isOk());

进入 Controller 的日期对象是不同的。

之前:2017-01-01T01:01:01.000000001Z

之后:2017-01-01T01:01:01.000000001Z[UTC]

最佳答案

2017-01-01T01:01:01.000000001Z2017-01-01T01:01:01.000000001Z[UTC] 这两个值实际上代表同一个时刻,所以它们是等价的,可以毫无问题地使用(至少应该没有问题,因为它们代表相同的时刻)。

唯一的细节是 Jackson,出于某种原因,在反序列化时将 ZoneId 值设置为“UTC”,这在这种情况下是多余的(Z 已经告诉偏移量是“UTC”)。但它不应影响日期值本身。


摆脱此 [UTC] 部分的一种非常简单的方法是将此对象转换为 OffsetDateTime(因此它保留 Z偏移并且不使用 [UTC] 时区)然后再次返回到 ZonedDateTime:

ZonedDateTime z = // object with 2017-01-01T01:01:01.000000001Z[UTC] value
z = z.toOffsetDateTime().toZonedDateTime();
System.out.println(z); // 2017-01-01T01:01:01.000000001Z

在那之后,z 变量的值将是 2017-01-01T01:01:01.000000001Z(没有 [UTC]部分)。

当然,这并不理想,因为您必须为所有日期手动执行此操作。更好的方法是编写自定义反序列化器(通过扩展 com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer),在 UTC 时不设置时区:

public class CustomZonedDateTimeDeserializer extends InstantDeserializer<ZonedDateTime> {
public CustomZonedDateTimeDeserializer() {
// most parameters are the same used by InstantDeserializer
super(ZonedDateTime.class,
DateTimeFormatter.ISO_ZONED_DATE_TIME,
ZonedDateTime::from,
// when zone id is "UTC", use the ZoneOffset.UTC constant instead of the zoneId object
a -> ZonedDateTime.ofInstant(Instant.ofEpochMilli(a.value), a.zoneId.getId().equals("UTC") ? ZoneOffset.UTC : a.zoneId),
// when zone id is "UTC", use the ZoneOffset.UTC constant instead of the zoneId object
a -> ZonedDateTime.ofInstant(Instant.ofEpochSecond(a.integer, a.fraction), a.zoneId.getId().equals("UTC") ? ZoneOffset.UTC : a.zoneId),
// the same is equals to InstantDeserializer
ZonedDateTime::withZoneSameInstant, false);
}
}

然后你必须注册这个反序列化器。如果您使用 ObjectMapper,则需要将此添加到 JavaTimeModule:

ObjectMapper objectMapper = new ObjectMapper();
JavaTimeModule module = new JavaTimeModule();
// add my custom deserializer (this will affect all ZonedDateTime deserialization)
module.addDeserializer(ZonedDateTime.class, new CustomZonedDateTimeDeserializer());
objectMapper.registerModule(module);

如果你在 Spring 中配置它,配置将是这样的(未测试):

<bean class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean" id="pnxObjectMapper">
<property name="deserializersByType">
<map key-type="java.lang.Class">
<entry>
<key>
<value>java.time.ZonedDateTime</value>
</key>
<bean class="your.app.CustomZonedDateTimeDeserializer">
</bean>
</entry>
</map>
</property>
</bean>

关于java - jackson jsr310 中缺少 ZonedDateTimeDeserializer,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45213696/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com