我在对正在使用的服务进行反序列化时使用的类中有以下字段。
private ZonedDateTime transactionDateTime;
我使用的服务可能会使用以下模式返回Date或DateTime:yyyy-MM-dd'T'HH:mm:ss.SSSZ
让我举两个服务返回的例子:
- 2015年11月18日18:05:38.000+0200
- 2015年11月18日00:00:00.000+0200
虽然第一个运行良好,但后者会在反序列化过程中引发以下异常:
java.time.format.DateTimeParseException:文本无法在索引23 处分析"2015-11-18T00:00:00.000+0200"
我正在使用;
- 弹簧套1.3.1
- Jackson 2.6.4(包含JSR310模块)
这需要自定义反序列化类吗?
Jackson反序列化程序默认情况下将绕过时区信息,并使用上下文时区来覆盖它,所有ISO8601都将以UTC结束。
使用Spring,此功能可以通过以下方式关闭:
spring.jackson.deserialization.ADJUST_DATES_TO_CONTEXT_TIME_ZONE=false
您可以使用以下注释
@JsonSerialize(using = MyCustomJsonDateSerializer.class)
或
@JsonDeserialize(using = MyCustomJsonDateDeserializer.class)
自定义Jackson解析日期的方式。这些自定义序列化程序和反序列化程序必须扩展JsonSerializer和JsonDeserializer。例如:
public class MyCustomJsonDateSerializer extends JsonSerializer<Date> {
@Override
public void serialize(Date date, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeString(date != null ? ISODateTimeFormat.dateTime().print(new DateTime(date)) : null);
}
}
在代码的早期,我使用了带有@JsonFormat
注释的字段,但删除了它,因为我认为它只是像JavaDocs建议的那样用于序列化。
结果我需要加回那个注释。真正的问题是第三方服务响应确实是错误的(它在XML中缺少一个包装器元素),这导致了取消序列化失败。错误是:
com.fasterxml.jackson.databind.JsonMappingException:无法实例化类型[简单类型,类com.foo.bar.adapter.john.model.account.UserAccount]from字符串值('2015-11-18T00:00:00.000+0200');没有单个字符串构造函数/工厂方法
该字段如下所示:
@JsonFormat(pattern = Constants.DATETIME_FORMAT)
@JacksonXmlProperty(localName = "transactionDate")
private ZonedDateTime transactionDateTime;
此外,我不得不将@JsonRootName("transaction")
添加到该字段的类中,因为对象被包装到集合中。
我用过
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
private ZonedDateTime startDate;
加上jackson-datatype-jsr310
文库。
该解决方案在Jackson中将ISO8601格式的日期时间反序列化为Java8 Instant 中进行了描述
以下配置帮助了我
指定日期时间模式:
public class Timestamp {
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssXXX")
private ZonedDateTime timestamp;
}
禁用将ZonedDateTime转换为UTC:
objectMapper.configure(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE, false);
另外还有一个问题,可能很难发现。在我的案例中,我使用RestTemplate从另一个微服务接收Timestamp
。RestTemplate可以被配置为使用notProjectDefaultObjectMapper
,它不受默认的Spring Jackson配置方法的影响(如应用程序属性,或具有Jackson2ObjectMapperBuilderCustomizer
bean定义的@Configuration
类或其他)。因此RestTemplate的objectMapper(如果有)也应该配置