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

后端 未结 10 1407
小蘑菇
小蘑菇 2020-11-29 02:35

I use Spring Boot and included jackson-datatype-jsr310 with Maven:


    com.fasterxml.jackson.datatype

        
相关标签:
10条回答
  • 2020-11-29 02:52

    Like I put in the comment, you could also use this solution in the signature method: @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime start

    0 讨论(0)
  • 2020-11-29 02:52

    The answers above didn't work for me, but I blundered on to one which did here: https://blog.codecentric.de/en/2017/08/parsing-of-localdate-query-parameters-in-spring-boot/ The winning snippet was the ControllerAdvice annotation, which has the advantage of applying this fix across all your controllers:

    @ControllerAdvice
    public class LocalDateTimeControllerAdvice
    {
    
        @InitBinder
        public void initBinder( WebDataBinder binder )
        {
            binder.registerCustomEditor( LocalDateTime.class, new PropertyEditorSupport()
            {
                @Override
                public void setAsText( String text ) throws IllegalArgumentException
                {
                    LocalDateTime.parse( text, DateTimeFormatter.ISO_DATE_TIME );
                }
            } );
        }
    }
    
    0 讨论(0)
  • 2020-11-29 02:56

    You can add to config, this solution does work with optional as well as with non-optional parameters.

    @Bean
        public Formatter<LocalDate> localDateFormatter() {
            return new Formatter<>() {
                @Override
                public LocalDate parse(String text, Locale locale) {
                    return LocalDate.parse(text, DateTimeFormatter.ISO_DATE);
                }
    
                @Override
                public String print(LocalDate object, Locale locale) {
                    return DateTimeFormatter.ISO_DATE.format(object);
                }
            };
        }
    
    
        @Bean
        public Formatter<LocalDateTime> localDateTimeFormatter() {
            return new Formatter<>() {
                @Override
                public LocalDateTime parse(String text, Locale locale) {
                    return LocalDateTime.parse(text, DateTimeFormatter.ISO_DATE_TIME);
                }
    
                @Override
                public String print(LocalDateTime object, Locale locale) {
                    return DateTimeFormatter.ISO_DATE_TIME.format(object);
                }
            };
        }
    
    
    0 讨论(0)
  • 2020-11-29 02:58

    Following works well with Spring Boot 2.1.6:

    Controller

    @Slf4j
    @RestController
    public class RequestController {
    
        @GetMapping
        public String test(RequestParameter param) {
            log.info("Called services with parameter: " + param);
            LocalDateTime dateTime = param.getCreated().plus(10, ChronoUnit.YEARS);
            LocalDate date = param.getCreatedDate().plus(10, ChronoUnit.YEARS);
    
            String result = "DATE_TIME: " + dateTime + "<br /> DATE: " + date;
            return result;
        }
    
        @PostMapping
        public LocalDate post(@RequestBody PostBody body) {
            log.info("Posted body: " + body);
            return body.getDate().plus(10, ChronoUnit.YEARS);
        }
    }
    

    Dto classes:

    @Value
    public class RequestParameter {
        @DateTimeFormat(iso = DATE_TIME)
        LocalDateTime created;
    
        @DateTimeFormat(iso = DATE)
        LocalDate createdDate;
    }
    
    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public class PostBody {
        LocalDate date;
    }
    

    Test class:

    @RunWith(SpringRunner.class)
    @WebMvcTest(RequestController.class)
    public class RequestControllerTest {
    
        @Autowired MockMvc mvc;
        @Autowired ObjectMapper mapper;
    
        @Test
        public void testWsCall() throws Exception {
            String pDate        = "2019-05-01";
            String pDateTime    = pDate + "T23:10:01";
            String eDateTime = "2029-05-01T23:10:01"; 
    
            MvcResult result = mvc.perform(MockMvcRequestBuilders.get("")
                .param("created", pDateTime)
                .param("createdDate", pDate))
              .andExpect(status().isOk())
              .andReturn();
    
            String payload = result.getResponse().getContentAsString();
            assertThat(payload).contains(eDateTime);
        }
    
        @Test
        public void testMapper() throws Exception {
            String pDate        = "2019-05-01";
            String eDate        = "2029-05-01";
            String pDateTime    = pDate + "T23:10:01";
            String eDateTime    = eDate + "T23:10:01"; 
    
            MvcResult result = mvc.perform(MockMvcRequestBuilders.get("")
                .param("created", pDateTime)
                .param("createdDate", pDate)
            )
            .andExpect(status().isOk())
            .andReturn();
    
            String payload = result.getResponse().getContentAsString();
            assertThat(payload).contains(eDate).contains(eDateTime);
        }
    
    
        @Test
        public void testPost() throws Exception {
            LocalDate testDate = LocalDate.of(2015, Month.JANUARY, 1);
    
            PostBody body = PostBody.builder().date(testDate).build();
            String request = mapper.writeValueAsString(body);
    
            MvcResult result = mvc.perform(MockMvcRequestBuilders.post("")
                .content(request).contentType(APPLICATION_JSON_VALUE)
            )
            .andExpect(status().isOk())
            .andReturn();
    
            ObjectReader reader = mapper.reader().forType(LocalDate.class);
            LocalDate payload = reader.readValue(result.getResponse().getContentAsString());
            assertThat(payload).isEqualTo(testDate.plus(10, ChronoUnit.YEARS));
        }
    
    }
    
    0 讨论(0)
提交回复
热议问题