21

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;
TylerH
  • 20,799
  • 66
  • 75
  • 101
Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
  • 1
    I don't know that it uses `parse`, but have you added the appropriate extension, [here](https://github.com/FasterXML/jackson-datatype-jsr310)? – Sotirios Delimanolis May 11 '16 at 14:52
  • 1
    @SotiriosDelimanolis, no, how does it solve my problem? I need to specify the factory method. `LocalDateTime.parse("2016-05-11T17:32:20.897")` works fine. – Andrew Tobilko May 11 '16 at 15:02

3 Answers3

31

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.

Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
9

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;
}
Yan Khonski
  • 12,225
  • 15
  • 76
  • 114
  • @András are you saying that when you do a post request the LocalDateTime is null within your ClientRestObject? I'm having the same issue, and was wondering how you resolved it. – Steve May 11 '18 at 13:53
  • maybe late to the party but checkout the accepted answer here: https://stackoverflow.com/questions/40327970/deserialize-java-8-localdatetime-with-jacksonmapper – caniaskyouaquestion Apr 25 '19 at 08:13
0
ObjectMapper objectMapper = new ObjectMapper();
//To parse LocalDateTime
objectMapper.registerModule(new JavaTimeModule());

This works for me, Thanks !