title: no String-argument constructor/factory method to deserialize from String value ('2018-12-14')
body: <p>This question is almost same as <a href="https://stackoverflow.com/questions/45110371/no-string-argument-constructor-factory-method-to-deserialize-from-string-value">this</a> one, but it differs in that I am trying to get String to LocalDate. Here is error from STS: </p>
  
  <blockquote>
    <p>2018-12-14 00:47:04.507  WARN 6216 --- [nio-8080-exec-2]
    .w.s.m.s.DefaultHandlerExceptionResolver : Resolved
    [org.springframework.http.converter.HttpMessageNotReadableException:
    JSON parse error: Can not construct instance of java.time.LocalDate:
    no String-argument constructor/factory method to deserialize from
    String value ('2018-12-14'); 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
    ('2018-12-14')  at [Source: java.io.PushbackInputStream@73ff9989;
    line: 3, column: 16] (through reference chain:
    com.xxxxx.xxxxxx.model.request.ReservationRequest["checkin"])]</p>
  </blockquote>
  
  <p>and here is from Postman:</p>
  
  <blockquote>
    <p>{
        "timestamp": 1544744824516,
        "status": 400,
        "error": "Bad Request",
        "exception": "org.springframework.http.converter.HttpMessageNotReadableException",
        "message": "JSON parse error: Can not construct instance of java.time.LocalDate: no String-argument constructor/factory method to
    deserialize from String value ('2018-12-14'); 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
    ('2018-12-14')\n at [Source: java.io.PushbackInputStream@73ff9989;
    line: 3, column: 16] (through reference chain:
    com.xxxxx.xxxxx.model.request.ReservationRequest[\"checkin\"])",
        "path": "/room/reservation/v1" }</p>
  </blockquote>
  
  <p>And POST request was:</p>
  
  <pre><code>{
      "id": 12345,
      "checkin": "2018-12-14",
      "checkout": "2018-12-17"
  }
  </code></pre>
  
  <p>Where relevant classes are: </p>
  
  <pre><code>import org.springframework.context.annotation.Bean;
  import org.springframework.context.annotation.Configuration;
  import com.fasterxml.jackson.databind.ObjectMapper;
  import com.fasterxml.jackson.databind.ObjectWriter;
  import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
  
  @Configuration
  public class ApiConfig {
  
      @Bean
      public ObjectMapper objectMapper() {
          ObjectMapper objectMapper = new ObjectMapper();
          objectMapper.registerModule(new JavaTimeModule());
          return new ObjectMapper();
      }
  
      @Bean
      public ObjectWriter objectWriter(ObjectMapper objectMapper) {
          return objectMapper.writerWithDefaultPrettyPrinter();
      }
  }
  </code></pre>
  
  <p>and </p>
  
  <pre><code>import java.time.LocalDate;
  import org.springframework.format.annotation.DateTimeFormat;
  
  public class ReservationRequest {
  
      private Long id;
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
      private LocalDate checkin;
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
      private LocalDate checkout;
  
      public ReservationRequest() {
          super();
      }
  
      public ReservationRequest(Long id, LocalDate checkin, LocalDate checkout) {
          super();
          this.id = id;
          this.checkin = checkin;
          this.checkout = checkout;
      }
  
      public Long getId() {
          return id;
      }
  
      public void setId(Long id) {
          this.id = id;
      }
  
      public LocalDate getCheckin() {
          return checkin;
      }
  
      public void setCheckin(LocalDate checkin) {
          this.checkin = checkin;
      }
  
      public LocalDate getCheckout() {
          return checkout;
      }
  
      public void setCheckout(LocalDate checkout) {
          this.checkout = checkout;
      }
  }
  </code></pre>
  
  <p>and </p>
  
  <pre><code>import org.springframework.format.annotation.DateTimeFormat;
  import org.springframework.http.HttpStatus;
  import org.springframework.http.MediaType;
  import org.springframework.http.ResponseEntity;
  import org.springframework.web.bind.annotation.PathVariable;
  import org.springframework.web.bind.annotation.RequestBody;
  import org.springframework.web.bind.annotation.RequestMapping;
  import org.springframework.web.bind.annotation.RequestMethod;
  import org.springframework.web.bind.annotation.RequestParam;
  import org.springframework.web.bind.annotation.RestController;
  import com.xxxxx.xxxxxx.model.request.ReservationRequest;
  import com.xxxxx.xxxxxx.model.response.ReservationResponse;
  
  @RestController
  @RequestMapping(ResourceConstants.ROOM_RESERVATION_V1)
  public class ReservationResource {
  
      @RequestMapping(path = "", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
      public ResponseEntity&lt;ReservationResponse&gt; getAvaiableRooms(
              @RequestParam(value = "checkin") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate checkin,
              @RequestParam(value = "checkout") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate checkout) {
          return new ResponseEntity&lt;&gt;(new ReservationResponse(), HttpStatus.OK);
      }
  
      @RequestMapping(path = "", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
      public ResponseEntity&lt;ReservationResponse&gt; createReservation(@RequestBody ReservationRequest reservationRequest) {
  
          return new ResponseEntity&lt;&gt;(new ReservationResponse(), HttpStatus.CREATED);
      }
  
      @RequestMapping(path = "", method = RequestMethod.PUT, produces = MediaType.APPLICATION_JSON_UTF8_VALUE, consumes = MediaType.APPLICATION_JSON_UTF8_VALUE)
      public ResponseEntity&lt;ReservationResponse&gt; updateReservation(@RequestBody ReservationRequest reservationRequest) {
  
          return new ResponseEntity&lt;&gt;(new ReservationResponse(), HttpStatus.OK);
      }
  
      @RequestMapping(path = "/{reservationId}", method = RequestMethod.DELETE)
      public ResponseEntity&lt;Void&gt; deleteReservation(@PathVariable long reservationId) {
  
          return new ResponseEntity&lt;&gt;(HttpStatus.NO_CONTENT);
      }
  }
  </code></pre>
  
  <p>I've included imports just in case.</p>
  
  <p>Anyway, if I change ReservationRequest to have fields with Strings instead of LocalDate like this then it doesn't produce error</p>
  
  <pre><code>public class ReservationRequest {
  
      private Long id;
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
      private String checkin;
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
      private String checkout;
  
      public ReservationRequest() {
          super();
      }
  
      public ReservationRequest(Long id, String checkin, String checkout) {
          super();
          this.id = id;
          this.checkin = checkin;
          this.checkout = checkout;
      }
  
  (getters and setters updated as well)
  </code></pre>
  
  <p>JDK 1.8; springBootVersion = '1.5.17.RELEASE'; name: 'jackson-datatype-jsr310', version: '2.9.7'</p>
  
  <p>Question is why it doesn't work as intended with <strong>LocalDate</strong>?</p>
  
  <p>UPDATE: tried <a href="https://stackoverflow.com/questions/28802544/java-8-localdate-jackson-format">these</a> solutions, and added @JsonSerialize and @JsonDeserialize, as neither <code>objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);</code>
          or <code>objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);</code></p>
  
  <p>worked so now it looks like: </p>
  
  <pre><code>public class ReservationRequest {
  
      private Long id;
      @JsonSerialize(using = ToStringSerializer.class)
      @JsonDeserialize(using = LocalDateDeserializer.class)
      //@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
      private LocalDate checkin;
      @JsonSerialize(using = ToStringSerializer.class)
      @JsonDeserialize(using = LocalDateDeserializer.class)
      //@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
      @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
      private LocalDate checkout;
  
      public ReservationRequest() {
          super();
      }
  </code></pre>
  
  <p>So, now it looks like it works but I don't know if it is good solution?</p>