Liam Park
Liam Park

Reputation: 511

TypeMismatch error with LocalDate as a param in GET request

I have the filter class bellow with 3 attributes to search for available books. I have two search cases: search through a list of book codes or search by date.

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class BookFilter {

    Set<Long> bookCodes;
    LocalDate fromDate;
    LocalDate toDate;

}

This is my Controller

    @GetMapping("/books")
    public ResponseEntity<Page<BookView>> findAvailableBooks(BookFilter bookFilter, Pageable pageable) {

        Page<Book> page = service.findAvailableBooks(bookFilter);
        Page<BookView> map = page.map(book-> modelMapper.map(book, BookView.class));

        return ResponseEntity.status(HttpStatus.OK).body(map);
    }

And I'm trying to send request in Postman like:

http://localhost:8887/v1/api/library/books?fromDate=01-01-2019&toDate=01-31-2019

But I'm stuck in typeMismatch error: Failed to convert from type String to LocalDate. What am I missing?

Upvotes: 1

Views: 2817

Answers (4)

S.Daineko
S.Daineko

Reputation: 1948

    /* 1. Get as String */
    @GetMapping("/books")
    ResponseEntity<Page<BookView>> findAvailableBooks(@RequestParam(value = "fromDate", required = false) String fromDate, @RequestParam(value = "toDate", required = false) String toDate, Pageable pageable) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");

        LocalDate fromLocalDate = LocalDate.parse(fromDate, formatter);
        LocalDate toLocalDate = LocalDate.parse(toDate, formatter);

        // other code
    }

    /* 2. Using @DateTimeFormat  */
    @GetMapping("/books")
    ResponseEntity<Page<BookView>> findAvailableBooks(@RequestParam(value = "fromDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime fromDate, @RequestParam(value = "toDate", required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME)  LocalDateTime toDate, Pageable pageable) {
        // other code
    }
  1. Send LocalDate as a String with @RequestParam and then convert it to the desired date format

  2. Use @DateTimeFormat (iso = DateTimeFormat.ISO.DATE_TIME) with the desired format in the date parameter

Also, a very similar question was asked before on this topic here:

How to use LocalDateTime RequestParam in Spring? I get "Failed to convert String to LocalDateTime"

Upvotes: 2

Michael Gantman
Michael Gantman

Reputation: 7790

You need to add @JsonFormat annotation to your LocalDate members

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class BookFilter {

    Set<Long> bookCodes;
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
    LocalDate fromDate;
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy")
    LocalDate toDate;
}

See this question: Spring Data JPA - ZonedDateTime format for json serialization

Upvotes: 1

Sudheendra
Sudheendra

Reputation: 29

You can use custom serializer/deserializer for string to LocalDate conversion.

import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "MM-dd-yyyy")
@JsonDeserialize(using = LocalDateDeserializer.class)
@JsonSerialize(using = LocalDateSerializer.class)
private LocalDate toDate;

after adding the below dependencies

<dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
   <version>2.9.7</version>
</dependency>
<dependency>
   <groupId>com.fasterxml.jackson.datatype</groupId>
   <artifactId>jackson-datatype-jsr310</artifactId>
   <version>2.9.7</version>
</dependency>

Upvotes: 1

Raja Bhowmick
Raja Bhowmick

Reputation: 37

Add @JsonFormat(pattern = "dd-MM-yyyy") before LocalDate So your BookFilter class will look like this

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class BookFilter {

    Set<Long> bookCodes;
    @JsonFormat(pattern = "dd-MM-yyyy")
    LocalDate fromDate;
    @JsonFormat(pattern = "dd-MM-yyyy")
    LocalDate toDate;

}

Upvotes: 1

Related Questions