Search code examples
javajsonserializationjacksonlocaldate

Jackson LocalDate module registered still exception


I wanted to serialize list with different objects of the class Personwith a firstname, lastname and a birthday. After looking at different questions in the forum here I found out that I need to register the jsr.310.JavaTimeModule to serialize the LocalDate birthday. I know there are many entries on this site regarding this topic but most of them say that registering the module is enough to handle the LocalDate.

This is my writer class:

public void write(){
    ArrayList<Person> personList = new ArrayList<>();

    Person p1 = new Person("Peter", "Griffin", LocalDate.of(1988,6,5));
    Person p2 = new Person("Lois", "Griffin", LocalDate.of(1997,9,22));

    personList.add(p1);
    personList.add(p2);

    ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());
    ObjectWriter writer = mapper.writer(new DefaultPrettyPrinter());

    try {
        writer.writeValue(new File(System.getProperty("user.dir")+"/File/Personen.json"), personList);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

and my Reader class is:

 public void read(){
    ObjectMapper mapper = new ObjectMapper();

    try {
        ArrayList<Person> liste = mapper.readValue(new FileInputStream("File/Personen.json"),
                mapper.getTypeFactory().constructCollectionType(ArrayList.class, Person.class));
        System.out.println(liste.get(0).getFirstname());
    } catch (IOException e) {
        e.printStackTrace();
    }
}

After reading the file I get a

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of java.time.LocalDate (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('1988-06-05')
at [Source: (FileInputStream); line: 4, column: 18] (through reference chain: java.util.ArrayList[0]->Person["birthday"])

I thought I don't need to do anything more than registering the TimeModule. Do I need to register a module for the reader as well? Or is there another problem with my code?


Solution

  • You correctly registered the JavaTimeModule with the ObjectMapper in your write() method.

    ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());
    

    But you forgot to register it with the ObjectMapper in your read() method.

    ObjectMapper mapper = new ObjectMapper();
    

    To fix it, just add the missing .registerModule(new JavaTimeModule()) there.

    Or better yet:
    Remove the local ObjectMapper definitions from your write and read methods. Instead, add it as a member variable to your class, so that you can use the same ObjectMapper instance in both methods.

    private ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());