I'm trying to deserialize a String
to LocalDateTime
with Jackson but it doesn't work.
I have a data class with a LocalDateTime field:
@Data
public class Registration {
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
private LocalDateTime timestamp;
}
I added the special Jackson datatype modules:
compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310")
The serialization works fine with:
new ObjectMapper().registerModule(new JavaTimeModule()).writeValueAsString(registration);
Result String:
{"timestamp":"2018-09-03 10:09:35"}
But the deserialization doesn't work with:
new ObjectMapper().registerModule(new JavaTimeModule()).readValue(json.traverse(), Registration.class)
As error I get:
Cannot deserialize value of type `java.time.LocalDateTime` from String "2018-09-03 10:09:35":
Failed to deserialize java.time.LocalDateTime:
(java.time.format.DateTimeParseException) Text '2018-09-03 10:09:35' could not be parsed:
Unable to obtain LocalDateTime from TemporalAccessor:
{MinuteOfHour=9, NanoOfSecond=0, SecondOfMinute=35, MicroOfSecond=0, MilliOfSecond=0, HourOfAmPm=10},
ISO resolved to 2018-09-03 of type java.time.format.Parsed
What am I missing? I'm confused that the serialization works but the deserialization doesn't.
MWE: (small gradle Java project)
Main.java:
import java.io.IOException;
import java.time.LocalDateTime;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
public class Main {
public static void main(String[] args) throws IOException {
Registration registration = new Registration();
registration.setTimestamp(LocalDateTime.now());
ObjectMapper objectMapper = new ObjectMapper().registerModule(new JavaTimeModule());
String s = objectMapper.writeValueAsString(registration);
TreeNode treeNode = objectMapper.readTree(s);
//Fails here:
Registration registration1 = objectMapper.readValue(treeNode.traverse(), Registration.class);
System.out.println(registration1);
}
}
class Registration {
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss")
private LocalDateTime timestamp;
public Registration() {
}
public LocalDateTime getTimestamp() {
return this.timestamp;
}
public void setTimestamp(LocalDateTime localDateTime) {
this.timestamp = localDateTime;
}
}
build.gradle:
plugins {
id 'java'
}
group 'dateMWE'
version '1.0-SNAPSHOT'
sourceCompatibility = 10
repositories {
mavenCentral()
}
dependencies {
compile("com.fasterxml.jackson.core:jackson-annotations:2.9.6")
compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.6")
}
The problem is not related with JSON deserialization, but rather with the time format string:
pattern = "yyyy-MM-dd hh:mm:ss"
Please notice that the hours are set as hh
: this is a 12-hour formatter, which requires "AM" or "PM" values.
If the pattern is changed to
pattern = "yyyy-MM-dd HH:mm:ss"
the problem should be solved.
Your ObjectMapper is not managed by spring since you are creating object with new. Configure ObjectMapper
as Bean in your configuration file. You need to register the DateTimeFormat
with your LocalDateTimeDeserializer
. Then set your Deserializer in JavaTimeModule.
@Bean
public ObjectMapper objectMapper() {
JavaTimeModule module = new JavaTimeModule();
LocalDateTimeDeserializer localDateTimeDeserializer = new
LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
module.addDeserializer(LocalDateTime.class, localDateTimeDeserializer);
ObjectMapper objectMapperObj = Jackson2ObjectMapperBuilder.json()
.modules(module)
.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.build();
return objectMapperObj;
}
Set the above configuration in your Spring configuration.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With