Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.2k views
in Technique[技术] by (71.8m points)

Cannot deserialize value of type `java.time.LocalDateTime` from String "2020-12-18 16:04:07-06"

I try to make java POJO with java.time packages, which binds the columns of "Federal Reserve Economic Data(FRED)" API. Some of these columns include time matters like below,

 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

So I make the following 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;

The realtime_start and realtime_end columns are successfully bound with FRED api. But the last_updated lines throws Exceptions.

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)

I think the json format patterns of realtime_start and realtime_end are correct with time format of actual value of FRED api (yyyy-MM-dd). But the last_updated columns throws the exception because the pattern yyyy-MM-dd HH:mm:sss Z is not correct with the string value from the FRED api(Text '2020-12-18 16:04:07-06'). I already insert various value 'Z', 'ZZ', 'x' in the json format pattern. But my every efforts fail. Any idea will be thankful? Best reagards.

== Updated

I solve my issue partly with below codes.

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);

My target goal is to make pojo class which contains DateTimeFormatter.ISO_DATE_TIME in JsonFormat of last_updated column. But I have no idea how to implement pojo class with DateTimeFormatter.ISO_DATE_TIME.

@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;

Kindly inform me of any advice. Best regards!

== Updated Again

So I make the JsonDeserialize class like below

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;
    }

}

And I change the JsonDeserialize class of pojo class,

@JsonProperty("last_updated")
@JsonDeserialize(using = DefaultLocalDateTimeDeserializer.class)
private LocalDateTime last_updated;

But the codes still throw the exceptions

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

I hope any reply will be helpful to this issue. Best regards.

question from:https://stackoverflow.com/questions/65866019/cannot-deserialize-value-of-type-java-time-localdatetime-from-string-2020-12

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You don't need to use deserializer. Use JSON format annotation as follows

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssZ")

See this question for more info: Spring Data JPA - ZonedDateTime format for json serialization

UPDATED: The mask mentioned above - "yyyy-MM-dd'T'HH:mm:ssZ" conforms to DateTimeFormatter.ISO_DATE_TIME. However, this format implements several possible masks. If you run toString() methof for DateTimeFormatter.ISO_DATE_TIME you will get the following output:

(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()']']]

For more details see Javadoc. The short answer is the same as before:

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ssZ")

Also, I can refer you to an article I wrote about how to implement parsing String to Date when you don't know the format in advance. The general idea is that you prepare the list of all formats that you'd like to support and try to parse your String with those formats one by one until you find one that works. There are, however, several details and implications in that solution. Also, some enhancements. See the article about it here: Java 8 java.time package: parsing any string to date


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

56.9k users

...