我正在尝试使用
java.time
包制作Java POJO,它绑定“联邦储备经济数据(FRED)”API的列。其中一些列包括时间问题,如下所示,
columns name example
---------------------------------------------
observation_end 2024-10-01 00:00:00
observation_start 2017-10-01 00:00:00
last_updated 2014-02-04 10:06:03-06:00
所以我制作了以下 Java POJO:
@Data
public class FredColumnPojo {
@JsonProperty("realtime_start")
@JsonFormat(pattern="yyyy-MM-dd")
@JsonDeserialize(using = LocalDateDeserializer.class)
private LocalDate realtime_start;
@JsonProperty("realtime_end")
@JsonFormat(pattern="yyyy-MM-dd")
@JsonDeserialize(using = LocalDateDeserializer.class)
private LocalDate realtime_end;
@JsonProperty("last_updated")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss Z")
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime last_updated;
realtime_start
和realtime_end
列已成功与FRED api绑定。但是 last_updated
行会抛出异常。
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.time.LocalDateTime` from String "2020-12-18 16:04:07-06": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2020-12-18 16:04:07-06' could not be parsed at index 19
at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: java.util.ArrayList[0]->com.aaa.etl.pojo.FredColumnPojo["last_updated"])
at com.fasterxml.jackson.databind.exc.InvalidFormatException.from(InvalidFormatException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.weirdStringException(DeserializationContext.java:1676)
at com.fasterxml.jackson.databind.DeserializationContext.handleWeirdStringValue(DeserializationContext.java:932)
at com.fasterxml.jackson.datatype.jsr310.deser.JSR310DeserializerBase._handleDateTimeException(JSR310DeserializerBase.java:176)
Caused by: java.time.format.DateTimeParseException: Text '2020-12-18 16:04:07-06' could not be parsed at index 19
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
我认为
realtime_start
和realtime_end
的json格式模式与FRED api实际值的时间格式(yyyy-MM-dd)是正确的。但 last_updated
列会引发异常,因为模式 yyyy-MM-dd HH:mm:sss Z 与 FRED api(Text '2020-12-18 16:04:07-06' )。我已经在 json 格式模式中插入了各种值“Z”、“ZZ”、“x”。但我所有的努力都失败了。
我用下面的代码部分解决了我的问题。
String input = "2014-02-04 10:06:03-06:00".replace(" ", "T");
DateTimeFormatter date = DateTimeFormatter.ISO_DATE_TIME;
LocalDateTime ldt = LocalDateTime.parse(input, date);
System.out.println(idt);
我的目标是制作在
DateTimeFormatter.ISO_DATE_TIME
列的JsonFormat中包含last_updated
的pojo类。但我不知道如何用 DateTimeFormatter.ISO_DATE_TIME 实现 pojo 类。
@JsonProperty("last_updated")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss Z") <-- How to set the pattern to DateTimeFormatter.ISO_DATE_TIME
private LocalDateTime last_updated;
所以我制作 JsonDeserialize 类,如下所示:
public class DefaultLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
// TODO Auto-generated method stub
String input = p.getText().replace(" ", "T");
DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE_TIME;
LocalDateTime localDateTime = LocalDateTime.parse(input, formatter);
return localDateTime;
}
}
我更改了 POJO 类的 JsonDeserialize 类:
@JsonProperty("last_updated")
@JsonDeserialize(using = DefaultLocalDateTimeDeserializer.class)
private LocalDateTime last_updated;
但是代码仍然抛出异常
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Text '2020-12-18T16:04:07-06' could not be parsed, unparsed text found at index 19 (through reference chain: java.util.ArrayList[0]->com.aaa.etl.pojo.FredColumnPojo["last_updated"])
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:394)
at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:353)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.wrapAndThrow(BeanDeserializerBase.java:1714)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:290)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:151)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:286)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:245)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:27)
at com.fasterxml.jackson.databind.ObjectMapper._readValue(ObjectMapper.java:4173)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2492)
at com.aaa.etl.processor.Fred2Hdfs.getEtlListData(Fred2Hdfs.java:146)
at com.aaa.etl.processor.EtlFileUploader.main(EtlFileUploader.java:39)
Caused by: java.time.format.DateTimeParseException: Text '2020-12-18T16:04:07-06' could not be parsed, unparsed text found at index 19
at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2049)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
at java.base/java.time.LocalDateTime.parse(LocalDateTime.java:492)
at com.aaa.etl.pojo.DefaultLocalDateTimeDeserializer.deserialize(DefaultLocalDateTimeDeserializer.java:20)
at com.aaa.etl.pojo.DefaultLocalDateTimeDeserializer.deserialize(DefaultLocalDateTimeDeserializer.java:1)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:288)
... 8 more
您不需要使用解串器。使用JSON格式注释如下
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssZ")
有关更多信息,请参阅此问题:Spring Data JPA - ZonedDateTime format for json Serialization
更新: 上述面罩 -
"yyyy-MM-dd'T'HH:mm:ssZ"
符合 DateTimeFormatter.ISO_DATE_TIME
。然而,这种格式实现了几种可能的掩码。如果您为 toString()
运行 DateTimeFormatter.ISO_DATE_TIME
方法,您将得到以下输出:
(ParseCaseSensitive(false)(Value(Year,4,10,EXCEEDS_PAD)'-'Value(MonthOfYear,2)'-'Value(DayOfMonth,2))'T'(Value(HourOfDay,2)':'Value(MinuteOfHour,2)[':'Value(SecondOfMinute,2)[Fraction(NanoOfSecond,0,9,DecimalPoint)]]))[Offset(+HH:MM:ss,'Z')['['ParseCaseSensitive(true)ZoneRegionId()']']]
有关更多详细信息,请参阅Javadoc。简短的答案与之前相同:
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssZ")
另外,我可以推荐你参考我写的一篇文章,内容是在你事先不知道格式的情况下如何实现解析 String to Date 。总体思路是,准备您想要支持的所有格式的列表,并尝试用这些格式一一解析您的字符串,直到找到一种有效的格式。然而,该解决方案中有几个细节和含义。另外,还有一些增强功能。请参阅此处有关它的文章:Java 8 java.time 包:解析迄今为止的任何字符串