Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LocalDateTime - deserialization with LocalDateTime.parse

I have the field initiationDate which serialises by ToStringSerializer class to ISO-8601 format.

@JsonSerialize(using = ToStringSerializer.class)
private LocalDateTime initiationDate;

When I receive the following JSON,

...
"initiationDate": "2016-05-11T17:32:20.897",
...

I want to deserialize it by LocalDateTime.parse(CharSequence text) factory method. All my attempts ended with com.fasterxml.jackson.databind.JsonMappingException:

Can not instantiate value of type [simple type, class java.time.LocalDateTime] from String value ('2016-05-11T17:32:20.897'); no single-String constructor/factory method

How do I achieve that? How can I specify factory method?


EDIT:

The problem has been solved by including jackson-datatype-jsr310 module to the project and using @JsonDeserialize with LocalDateTimeDeserializer.

@JsonSerialize(using = ToStringSerializer.class)
@JsonDeserialize(using = LocalDateTimeDeserializer.class)
private LocalDateTime initiationDate;
like image 638
Andrew Tobilko Avatar asked May 11 '16 14:05

Andrew Tobilko


2 Answers

Vanilla Jackson doesn't have a way to deserialize a LocalDateTime object from any JSON string value.

You have a few options. You can create and register your own JsonDeserializer which will use LocalDateTime#parse.

class ParseDeserializer extends StdDeserializer<LocalDateTime> {
    public ParseDeserializer() {
        super(LocalDateTime.class);
    }

    @Override
    public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        return LocalDateTime.parse(p.getValueAsString()); // or overloaded with an appropriate format
    }
}
...
@JsonSerialize(using = ToStringSerializer.class)
@JsonDeserialize(using = ParseDeserializer.class)
private LocalDateTime initiationDate;

Or you can add Jackson's java.time extension to your classpath and register the appropriate Module with your ObjectMapper.

objectMapper.registerModule(new JavaTimeModule());

and let Jackson do the conversion for you. Internally, this uses LocalDateTime#parse with one of the standard formats. Fortunately, it supports values like

2016-05-11T17:32:20.897

out of the box.

like image 151
Sotirios Delimanolis Avatar answered Oct 18 '22 12:10

Sotirios Delimanolis


For those who want to parse custom date-time format.

1) Add dependency

compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.8.8"

2) Json annotation with date-time format

public class ClientRestObject {

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime timestamp;

}

3) Register Java8 module in ObjectMapper

private static ObjectMapper buildObjectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    //To parse LocalDateTime
    objectMapper.registerModule(new JavaTimeModule());
    return objectMapper;
}
like image 26
Yan Khonski Avatar answered Oct 18 '22 14:10

Yan Khonski