【问题标题】:Cannot deserialize value of type `java.time.LocalDateTime` from String "2020-12-18 16:04:07-06"无法从字符串“2020-12-18 16:04:07-06”反序列化“java.time.LocalDateTime”类型的值
【发布时间】:2021-01-24 00:30:11
【问题描述】:

我正在尝试使用 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_startrealtime_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_startrealtime_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);

我的目标是在 last_updated 列的 JsonFormat 中制作包含 DateTimeFormatter.ISO_DATE_TIME 的 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

【问题讨论】:

  • 您是否尝试过 Timestamp 而不是 LocalDateTime?
  • @AlejandroDeulofeu java.sql.Timestamp 类现在是遗留的,不应该因为设计缺陷而被使用。随着 JSR 310 的采用,旧的日期时间类已过时。带有时间和与 UTC 的偏移量的日期(例如 2014-02-04 10:06:03-06:00)的适当类是 OffsetDateTime
  • 请检查我再次更新的部分并通知我您的智能回复。

标签: java java-time


【解决方案1】:

您不需要使用反序列化器。使用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。但是,这种格式实现了几种可能的掩码。如果您为DateTimeFormatter.ISO_DATE_TIME 运行toString()methof,您将获得以下输出:

(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解析为Date。一般的想法是,您准备好要支持的所有格式的列表,并尝试使用这些格式一一解析您的字符串,直到找到一种有效的格式。但是,该解决方案有几个细节和含义。此外,还有一些增强功能。在此处查看有关它的文章:Java 8 java.time package: parsing any string to date

【讨论】:

  • 感谢您的回复。请检查我更新的部分。
猜你喜欢
  • 1970-01-01
  • 2020-07-26
  • 2017-09-06
  • 1970-01-01
  • 2019-08-09
  • 2016-10-01
  • 2017-03-24
  • 2019-06-16
  • 2019-11-24
相关资源
最近更新 更多