TIL(Today I Learned)

TIL - Java 8 date/time type `java.time.LocalDateTime` not supported

Happy._. 2024. 5. 20. 10:58

Spring Security를 사용해 로그인 처리를 할 때, 성공 시 응답 본문에 Json 형식의 데이터를 담아 보내려고 했다.

그런데 LocalDateTime 타입의 createdAt에 대해 다음과 같은 예외가 발생했다.

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: 
Java 8 date/time type `java.time.LocalDateTime` not supported by default: 
add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling 
(through reference chain: org.zerock.todolist.domain.user.dto.UserResponse["createdAt"])

 

Controller에서 응답 본문에 dto를 담아 보내는 것은 정상적으로 동작한다.

ResponseEntity.status(HttpStatus.OK).body(todoService.getTodoById(todoId))

 

 

위 문제를 해결하기 위해 objectMapper에 다음과 같이 JavaTimeModule을 등록해 준다.

objectMapper.registerModule(JavaTimeModule()).writeValue(response.writer, userToResponse)

 

JavaTimeModule

  • Java 8의 날짜 및 시간 API인 JSR-310 데이터 타입을 지원하는 에드온 모듈
  • LocalDateTime, LocalDate 등 Java 8의 날짜 및 시간 객체를 Json으로 직렬화/역직렬화하는 데 사용

JavaTimeModule을 설정하면 예외 없이 정상적으로 응답을 보낼 수 있다.

하지만 다음과 같이 createdAt(LocalDateTime)이 배열로 전달되는 것을 볼 수 있다.

 

위 문제를 해결하기 위해서 다음과 같이 LocalDateTime객체를 Json으로 직렬화 하는 코드를 추가한다.

dto에 @JsonSerialize(using = LocalDateTimeSerializer.class) 어노테이션을 붙여서 해결하는 방법도 있었는데 이 방법은 제대로 작동하지 않았다.

val DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss.SSSSSS"

objectMapper.registerModule(
    JavaTimeModule().addSerializer(
        LocalDateTime::class.java, LocalDateTimeSerializer(
            DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT))
        )
    )
.writeValue(response.writer, userToResponse)

 

위 코드를 추가하고 다시 프로젝트를 실행해 테스트 해보면 다음과 같이 정상적으로 출력되는 것을 볼 수 있다.

 

 

 

참고자료

https://green-bin.tistory.com/63