2

I have a simple rest service to store time range, however, Spring cannot parse datetime format with timezone correctly.

the Entity is

@Data
@Entity
public class TimeRange {
@Setter(AccessLevel.NONE)
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = true)
private LocalDateTime startTime;

@Column(nullable = true)
private LocalDateTime endTime;
}

The controller is:

@PostMapping(path = "/time", consumes = "application/json", produces = "application/json")
public Boolean setTime(@RequestBody TimeRange timeRange) {
    timeRangeRepository.save(timeRange);
    return true;
}

and the actuall request is

url = f'http://localhost/api/time'
data = {
  "startTime": "2019-12-03T19:58:29.047820+08:00",
  "endTime": "2019-12-04T19:58:29.047820+08:00"}
resp = requests.post(url, json=data, timeout=10)
pprint(resp.json())

spring reported an error said:

 esolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: 
Cannot deserialize value of type `java.time.LocalDateTime` from String "2019-12- 

03T19:58:29.047820+08:00": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2019-12-03T19:58:29.047820+08:00' could not be parsed, unparsed text found at index 26; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type java.time.LocalDateTime from String "2019-12-03T19:58:29.047820+08:00": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2019-12- 03T19:58:29.047820+08:00' could not be parsed, unparsed text found at index 26 at

Wangwang
  • 159
  • 1
  • 15
  • Does this answer your question? [serialize/deserialize java 8 java.time with Jackson JSON mapper](https://stackoverflow.com/questions/27952472/serialize-deserialize-java-8-java-time-with-jackson-json-mapper) – Glains Dec 09 '19 at 12:15
  • tried the jackson-modules-java8, it still get the same error, i might not be able to get findAndRegisterModules on the way. – Wangwang Dec 09 '19 at 12:26
  • Does this answer your question? [Spring Data JPA - ZonedDateTime format for json serialization](https://stackoverflow.com/questions/31627992/spring-data-jpa-zoneddatetime-format-for-json-serialization) – Michael Gantman Dec 09 '19 at 13:20
  • This is a duplicated question. Look at the question: [Spring Data JPA - ZonedDateTime format for json serialization](https://stackoverflow.com/questions/31627992/spring-data-jpa-zoneddatetime-format-for-json-serialization) – Michael Gantman Dec 09 '19 at 13:21
  • Do you intentionally want to deserialize to `java.time.LocalDateTime` (losing the zone informat) instead of `java.time.ZonedDateTime`? – Mark Rotteveel Dec 09 '19 at 18:41
  • @MichaelGantman That is not a duplicate of this question. Given that the OPs code is already deserializing to `java.time` classes, that is already setup, the problem is that they're trying to deserialize a timestamp with zone information to a `LocalDateTime`. – Mark Rotteveel Dec 09 '19 at 18:43

2 Answers2

1

You have a date with offset, if all your date comes in the same format you can create a custom deserializer like this

public class CustomLocalDateTimeDeserializer extends StdDeserializer<LocalDateTime> {
   private static final long serialVersionUID = 1L;

    public CustomLocalDateTimeDeserializer () {
        this(null);
    }

    protected CustomLocalDateTimeDeserializer (Class<?> vc) {
        super(vc);
    }

    @Override
    public LocalDateTime deserialize(JsonParser arg0, DeserializationContext arg1)
        throws IOException, JsonProcessingException {
        return LocalDateTime.parse(arg0.getValueAsString(), DateTimeFormatter.ISO_OFFSET_DATE_TIME);
    }

}

and the annotate your fields with @JsonDeserialize

@JsonDeserialize(using = CustomLocalDateTimeDeserializer.class)
private LocalDateTime startTime;

@JsonDeserialize(using = CustomLocalDateTimeDeserializer.class)
private LocalDateTime endTime;

And if you want to serialize your dates with the same format, you have to create a custom serializer

b.GHILAS
  • 2,273
  • 1
  • 8
  • 16
0

Annotate your LocalDateTime fields with:

@JsonSerialize(using = LocalDateTimeSerializer.class)
Sagar Ahuja
  • 637
  • 10
  • 10