使用可变小数秒数反序列化日期的Java日期模式?

时间:2017-02-14 23:14:43

标签: java parsing datetime jackson deserialization

我在Spring启动应用程序中使用了一个Java类来反序序列化来自请求的json对象,其字段如下:

@JsonFormat(pattern="yyyy-MM-dd'T'HH:mm:ss[.SSS]XXX", timezone = "UTC")
Instant timestamp;

它正在使用Jackson V2.6.6 @JsonFormat注释反序列化通过网络传输的JSON中的“timestamp”字段。

我所看到的是,当价值如下:

  

“2017-01-09T21:49:26.70Z”

没有问题。

但是,如果该值包含单个小数点后第二位小数,或者超过三位小数,则为:

  

“2017-01-09T21:49:26.7Z”或“2017-01-09T21:49:26.7000Z”

然后我会收到以下错误:

Caused by: java.time.format.DateTimeParseException: Text '2017-01-09T21:49:26.7Z' could not be parsed at index 19
    at java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1949) ~[?:1.8.0_65]
    at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1777) ~[?:1.8.0_65]
    at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:150) ~[jackson-datatype-jsr310-2.6.6.jar:2.6.6]
    at com.fasterxml.jackson.datatype.jsr310.deser.InstantDeserializer.deserialize(InstantDeserializer.java:45) ~[jackson-datatype-jsr310-2.6.6.jar:2.6.6]
    at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:520) ~[jackson-databind-2.6.6.jar:2.6.6]
    at com.fasterxml.jackson.databind.deser.impl.FieldProperty.deserializeAndSet(FieldProperty.java:101) ~[jackson-databind-2.6.6.jar:2.6.6]
    at com.fasterxml.jackson.module.afterburner.deser.SuperSonicBeanDeserializer.deserialize(SuperSonicBeanDeserializer.java:156) ~[jackson-module-afterburner-2.6.6.jar:2.6.6]
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3736) ~[jackson-databind-2.6.6.jar:2.6.6]
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2764) ~[jackson-databind-2.6.6.jar:2.6.6]

我可以做些什么来修复这个模式,以便它可以灵活地接受它接受的小数点后第二位数?我知道Java日期格式有一个宽松的概念:https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html

但我不确定如何将对象映射器设置为宽松模式。

1 个答案:

答案 0 :(得分:0)

更新您的Java实现

只是一个猜测......

我怀疑你可能在早期版本的Java 8中遇到了一些java.time错误。有几个解析相关的错误,一些在Java 8的后续更新中得到修复,一些在Java 9中得到修复。

我猜你的错误文本中的1.8.0_65字符串是指Java 8 Update 65.目前是Oracle implementation is at Update 121

什么格式化程序?

我不知道Jackson。我想知道他们正在调用的确切DateTimeFormatter。我在错误报价中没有看到这些信息。

您是否可以省略定义模式并查看杰克逊的默认行为?

Instant.parse

没问题

我在MacBook Pro(Retina,15英寸,2013年末)的Java 8 Update 121中调用Instant.parse解析字符串时看到没有这样的问题,其中16个内存运行macOS Sierra 10.12.3 NetBeans 8.2。

System.out.println ( "Java vendor: " + System.getProperty ( "java.vendor" ) );
System.out.println ( "Java version: " + System.getProperty ( "java.version" ) );

List<String> strings = new ArrayList<> ();
strings.add ( "2017-01-09T21:49:26.7Z" );
strings.add ( "2017-01-09T21:49:26.70Z" );
strings.add ( "2017-01-09T21:49:26.700Z" );
strings.add ( "2017-01-09T21:49:26.7000Z" );
strings.add ( "2017-01-09T21:49:26.70000Z" );

for ( String string : strings ) {
    try {
        Instant instant = Instant.parse ( string );
        System.out.println ( "GOOD - string: " + string + " parsed: " + instant );
    } catch ( DateTimeParseException e ) {
        System.out.println ( "ERROR - Failed to parse string: " + string );
    }
}
System.out.println ( "Done." );

跑步时。

Java vendor: Oracle Corporation
Java version: 1.8.0_121
GOOD - string: 2017-01-09T21:49:26.7Z parsed: 2017-01-09T21:49:26.700Z
GOOD - string: 2017-01-09T21:49:26.70Z parsed: 2017-01-09T21:49:26.700Z
GOOD - string: 2017-01-09T21:49:26.700Z parsed: 2017-01-09T21:49:26.700Z
GOOD - string: 2017-01-09T21:49:26.7000Z parsed: 2017-01-09T21:49:26.700Z
GOOD - string: 2017-01-09T21:49:26.70000Z parsed: 2017-01-09T21:49:26.700Z

您也可以毫无问题地看到同样的code run live at IdeOne.com,运行Oracle实现的Java 8 Update 121.

DateTimeFormatter.ofPattern

的问题

我也尝试了你的格式化模式。它适用于.70.700,但不适用于其他人。

DateTimeFormatter f = DateTimeFormatter.ofPattern ( "yyyy-MM-dd'T'HH:mm:ss[.SSS]XXX" , Locale.US );
for ( String string : strings ) {
    try {
        OffsetDateTime odt = OffsetDateTime.parse ( string , f );
        System.out.println ( "GOOD - string: " + string + " parsed: " + odt );
    } catch ( DateTimeParseException e ) {
        System.out.println ( "ERROR - Failed to parse string: " + string );
    }
}
System.out.println ( "Done with 'DateTimeFormatter.ofPattern'." );
ERROR - Failed to parse string: 2017-01-09T21:49:26.7Z
GOOD - string: 2017-01-09T21:49:26.70Z parsed: 2017-01-09T21:49:26.700Z
GOOD - string: 2017-01-09T21:49:26.700Z parsed: 2017-01-09T21:49:26.700Z
ERROR - Failed to parse string: 2017-01-09T21:49:26.7000Z
ERROR - Failed to parse string: 2017-01-09T21:49:26.70000Z

ISO 8601

仅供参考,2017-01-09T21:49:26.70Z等字符串的格式在ISO 8601标准中定义。在解析或生成表示日期时间值的字符串时,java.time类默认使用这些标准的ISO 8601格式。

该特定格式使用T将年 - 月 - 日期部分与小时 - 分 - 秒部分分开。 ZZulu的缩写,表示UTC

您可以通过searching StackOverflow查看更多信息。