8

Having class like this

@AllArgsConstructor @NoArgsConstructor @Getter @Setter public final class ActiveRecoveryProcess { private UUID recoveryId; private Instant startedAt; } 

I'm getting com.fasterxml.jackson.databind.exc.InvalidFormatException with message Cannot deserialize value of typejava.time.Instantfrom String "2020-02-22T16:37:23": Failed to deserialize java.time.Instant: (java.time.format.DateTimeParseException) Text '2020-02-22T16:37:23' could not be parsed at index 19

JSON input

{"startedAt": "2020-02-22T16:37:23", "recoveryId": "6f6ee3e5-51c7-496a-b845-1c647a64021e"} 

Jackson configuration

 @Autowired void configureObjectMapper(final ObjectMapper mapper) { mapper.registerModule(new ParameterNamesModule()) .registerModule(new Jdk8Module()) .registerModule(new JavaTimeModule()); mapper.findAndRegisterModules(); } 

EDIT

JSON is generated from postgres

jsonb_build_object( 'recoveryId', r.recovery_id, 'startedAt', r.started_at ) 

where r.started_at is TIMESTAMP.

3
  • Instant is being used over the whole project. Why should I consider using LocalDateTime over Instant? Commented Mar 5, 2020 at 19:18
  • 1
    If the incoming data just says 2020-02-22T16:37:23, without a Z at the end, how do you know for sure that the time is in UTC? Perhaps using LocalDateTime would be more appropriate for such a time value without time zone. Commented Mar 5, 2020 at 19:28
  • I edited my post - JSON is generated from Postgres, jsonb_build_object() function Commented Mar 5, 2020 at 19:31

2 Answers 2

6

The String you're trying to parse, 2020-02-22T16:37:23, doesn't end in Z. Instant expects this as it stands for UTC. It simply cannot be parsed. Concat the String with Z to resolve the issue.

 String customInstant = "2020-02-22T16:37:23"; System.out.println("Instant of: " + Instant.parse(customInstant.concat("Z"))); 
Sign up to request clarification or add additional context in comments.

1 Comment

JSON is generated by Postgres function jsonb_build_object(). So I changed SQL query to jsonb_build_object( 'recoveryId', r.recovery_id, 'startedAt', replace(concat(r.started_at, 'Z'), ' ', 'T'), and it helped. Thanks!
5

One way to do this is to create a Converter.

public final class NoUTCInstant implements Converter<LocalDateTime, Instant> { @Override public Instant convert(LocalDateTime value) { return value.toInstant(ZoneOffset.UTC); } @Override public JavaType getInputType(TypeFactory typeFactory) { return typeFactory.constructType(LocalDateTime.class); } @Override public JavaType getOutputType(TypeFactory typeFactory) { return typeFactory.constructType(Instant.class); } } 

Then annotate the field.

@JsonDeserialize(converter = NoUTCInstant.class) private Instant startedAt; 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.