Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON parse error: Can not construct instance of java.time.LocalDate: no String-argument constructor/factory method to deserialize from String value

I am new to Spring Data REST project and I am trying to create my first RESTful service. The task is simple, but I am stuck.

I want to perform CRUD operations on a user data stored in an embedded database using RESTful API.

But I cannot figure out how to make the Spring framework process the birthData as "1999-12-15" and store it as a LocalDate. The @JsonFormat annotation does not help.

At present I get the error:

HTTP/1.1 400  Content-Type: application/hal+json;charset=UTF-8 Transfer-Encoding: chunked Date: Thu, 24 Aug 2017 13:36:51 GMT Connection: close  {"cause":{"cause":null,"message":"Can not construct instance of java.time.LocalDate:  no String-argument constructor/factory method to deserialize from String value ('1999-10-10')\n  at [Source: org.apache.catalina.connector.CoyoteInputStream@4ee2a60e;  line: 1, column: 65] (through reference chain: ru.zavanton.entities.User[\"birthDate\"])"}, "message":"JSON parse error: Can not construct instance of java.time.LocalDate:  no String-argument constructor/factory method to deserialize from String value ('1999-10-10'); nested exception is com.fasterxml.jackson.databind.JsonMappingException:  Can not construct instance of java.time.LocalDate: no String-argument constructor/factory method to deserialize from String value ('1999-10-10')\n  at [Source: org.apache.catalina.connector.CoyoteInputStream@4ee2a60e; line: 1, column: 65] (through reference chain: ru.zavanton.entities.User[\"birthDate\"])"} 

How to make it work, so that client calls like:

curl -i -X POST -H "Content-Type:application/json" -d "{  \"firstName\" : \"John\",  \"lastName\" : \"Johnson\", \"birthDate\" : \"1999-10-10\", \"email\" : \"[email protected]\" }" http://localhost:8080/users 

will actually store the entity into the database.

Below is the information about the classes.

The user class:

package ru.zavanton.entities;   import com.fasterxml.jackson.annotation.JsonFormat;  import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import java.time.LocalDate;  @Entity public class User {      @Id     @GeneratedValue(strategy = GenerationType.AUTO)     private long id;      private String firstName;     private String lastName;      @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")     private LocalDate birthDate;      private String email;     private String password;      public long getId() {         return id;     }      public void setId(long id) {         this.id = id;     }      public String getFirstName() {         return firstName;     }      public void setFirstName(String firstName) {         this.firstName = firstName;     }      public String getLastName() {         return lastName;     }      public void setLastName(String lastName) {         this.lastName = lastName;     }      public LocalDate getBirthDate() {         return birthDate;     }      public void setBirthDate(LocalDate birthDate) {         this.birthDate = birthDate;     }      public String getEmail() {         return email;     }      public void setEmail(String email) {         this.email = email;     }      public String getPassword() {         return password;     }      public void setPassword(String password) {         this.password = password;     } } 

The UserRepository class:

package ru.zavanton.repositories;  import org.springframework.data.repository.PagingAndSortingRepository; import org.springframework.data.repository.query.Param; import org.springframework.data.rest.core.annotation.RepositoryRestResource; import ru.zavanton.entities.User;  @RepositoryRestResource(collectionResourceRel = "users", path = "users") public interface UserRepository extends PagingAndSortingRepository<User, Long> {      User findByEmail(@Param("email") String email);  } 

Application class:

package ru.zavanton;  import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;  @SpringBootApplication public class Application {      public static void main(String[] args) {          SpringApplication.run(Application.class, args);      } } 
like image 984
zavanton Avatar asked Aug 24 '17 14:08

zavanton


1 Answers

You need jackson dependency for this serialization and deserialization.

Add this dependency:

Gradle:

compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.9.4") 

Maven:

<dependency>     <groupId>com.fasterxml.jackson.datatype</groupId>     <artifactId>jackson-datatype-jsr310</artifactId> </dependency> 

After that, You need to tell Jackson ObjectMapper to use JavaTimeModule. To do that, Autowire ObjectMapper in the main class and register JavaTimeModule to it.

import javax.annotation.PostConstruct; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;  @SpringBootApplication public class MockEmployeeApplication {    @Autowired   private ObjectMapper objectMapper;    public static void main(String[] args) {     SpringApplication.run(MockEmployeeApplication.class, args);    }    @PostConstruct   public void setUp() {     objectMapper.registerModule(new JavaTimeModule());   } } 

After that, Your LocalDate and LocalDateTime should be serialized and deserialized correctly.

like image 164
SanketKD Avatar answered Sep 22 '22 06:09

SanketKD