jsondatetimejacksonzoneddatetime

ZonedDateTime cannot be parsed from JSON, but parses fine with the formatter


I have this date string coming in through JSON: "29-OCT-21 12.00.00.000000000 AM UTC". I want to save it as a ZonedDateTime data type.

I have the property set in the model as such:

  @JsonProperty("createdTs")
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MMM-yy hh.mm.ss.SSSSSSSSS a z", with = JsonFormat.Feature.ACCEPT_CASE_INSENSITIVE_PROPERTIES)
    private ZonedDateTime createdTs;

I am getting an error:

org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.time.ZonedDateTime` from String "29-OCT-21 12.00.00.000000000 AM UTC": Failed to deserialize java.time.ZonedDateTime: (java.time.format.DateTimeParseException) Text '29-OCT-21 12.00.00.000000000 AM UTC' could not be parsed 

I can't figure out what is wrong. The pattern works just fine in the formatter in test cases, like this:

DateTimeFormatter formatter = new DateTimeFormatterBuilder().parseCaseInsensitive().appendPattern("dd-MMM-yy hh.mm.ss.SSSSSSSSS a z").toFormatter(
        Locale.getDefault());
    locationPayload.setcreatedTs(ZonedDateTime.parse("29-OCT-21 12.00.00.000000000 AM UTC", formatter));

Solution

  • This issue is related to the inability of the JsonFormat to handle the complex date-time format you have in the JSON string. To resolve this, you can create a custom deserializer for the ZonedDateTime type.

    Here's an example:

    import com.fasterxml.jackson.core.JsonParser;
    import com.fasterxml.jackson.databind.DeserializationContext;
    import com.fasterxml.jackson.databind.JsonDeserializer;
    import java.io.IOException;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    
    public class ZonedDateTimeDeserializer extends JsonDeserializer<ZonedDateTime> {
    
        private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
                .parseCaseInsensitive()
                .appendPattern("dd-MMM-yy hh.mm.ss.SSSSSSSSS a z")
                .toFormatter();
    
        @Override
        public ZonedDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
            String dateString = jsonParser.getText();
            return ZonedDateTime.parse(dateString, FORMATTER);
        }
    }
    
    

    Your property

    public class Test {
    
        @JsonProperty("createdTs")
        @JsonDeserialize(using = ZonedDateTimeDeserializer.class)
        private ZonedDateTime createdTs;
    //Getter & Settere
    }
    

    Test

        public static void main(String[] args) throws JsonProcessingException {
            String s = """
                    {
                    "createdTs": "29-OCT-21 12.00.00.000000000 AM UTC"
                    }
                    """;
    
            Test t = JsonMapper.builder().findAndAddModules().build().readValue(s, Test.class);
    
            System.out.println(t);
        }
    

    Output Test(createdTs=2021-10-29T00:00Z[UTC])

    Try it and let me know