I try to use Jackson to deserialize LocalDateTime parameters, but when I use @RequestParam, it doesn't work, the 'deserialize' method has never been called.
Here is my @RequestParam method:
@GetMapping("/search")
public String search(
@JsonDeserialize(using = CustomLocalDateTimeDeserializer.class)
@RequestParam(value = "startTime", required = false) LocalDateTime startTime,
@JsonDeserialize(using = CustomLocalDateTimeDeserializer.class)
@RequestParam(value = "endTime", required = false) LocalDateTime endTime
)
Instead of @RequestParam, when I use @RequestBody accept parameters, and the 'deserialize' meothd will be called, so, what can I do for @RequestParam to use 'deserialize' method.
Here is my @RequestBody method:
@PostMapping("/test")
public LocalDateTime getBillingListByDate(@RequestBody SearchQuery searchQuery) {
return searchQuery.getStartTime();
}
SearchQuery:
public class SearchQuery {
@JsonDeserialize(using = CustomLocalDateTimeDeserializer.class)
private LocalDateTime startTime;
@JsonDeserialize(using = CustomLocalDateTimeDeserializer.class)
private LocalDateTime endTime;
// getter and setter
}
This is my Deserializer class:
public class CustomLocalDateTimeDeserializer extends StdDeserializer<LocalDateTime> {
private final DateTimeFormatter FORMATTER1 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private final DateTimeFormatter FORMATTER2 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
public CustomLocalDateTimeDeserializer() {
this(LocalDateTime.class);
}
CustomLocalDateTimeDeserializer(Class<LocalDateTime> deserializer) {
super(deserializer);
}
@Override
public LocalDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
String text = jsonParser.getText().trim();
if (ObjectUtils.isEmpty(text)) {
return null;
}
LocalDateTime localDateTime = null;
try {
localDateTime = LocalDateTime.parse(text, FORMATTER1);
} catch (Exception e) {
try {
LocalDate parse = LocalDate.parse(text, FORMATTER2);
LocalTime time = LocalTime.of(0, 0, 0);
localDateTime = LocalDateTime.of(parse, time);
} catch (Exception ignore) {
}
}
return localDateTime;
}
}
and the config:
@Configuration
public class GlobalDateConfig {
private final String formatter = "yyyy-MM-dd HH:mm:ss";
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer() {
return builder -> {
DateTimeFormatter localDateTimeFormatter = DateTimeFormatter.ofPattern(formatter);
builder.serializerByType(LocalDateTime.class, new LocalDateTimeSerializer(localDateTimeFormatter));
builder.deserializerByType(LocalDateTime.class, new CustomLocalDateTimeDeserializer());
};
}
}
Here is my dependency version:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.11.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>2.11.2</version>
</dependency>
First, create a converter class
@Component
public class LocalDateTimeConverter implements Converter<String, LocalDateTime> {
@Override
public LocalDateTime convert(String value) {
try {
return LocalDate.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd")).atStartOfDay();
} catch (DateTimeParseException e1) {
try {
return LocalDateTime.parse(value, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
} catch (DateTimeParseException ignored) {
}
}
return null;
}
}
Then config it
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new LocalDateTimeConverter());
}
}
You can test it with these
/search?startTime=2023-03-31 03:10:02
/search?startTime=2023-03-31