-
Kotlin ObjectMapper 주의사항Spring Framework 2023. 11. 14. 00:01728x90
개요
Kotlin에서는 직렬화 역직렬화를 위해 Jackson을 지원합니다.
의존성 추가
Maven
<dependency> <groupId>com.fasterxml.jackson.module</groupId> <artifactId>jackson-module-kotlin</artifactId> <version>2.15.3</version> </dependency>
Gradle(Kotlin)
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.15.3")
테스트 클래스
data class Movie( var name: String, var studio: String, var rating: Float? = 1f, )
jacksonObjectMapper 테스트
@Test fun `kotlin에서 지원하는 jacksonObjectMapper를 사용해보기`(){ val objectMapper = jacksonObjectMapper() val movie = Movie("Endgame", "Marvel", 9.2f) val serialized = objectMapper.writeValueAsString(movie) val json = """ {"name":"Endgame","studio":"Marvel","rating":9.2} """.trimIndent() assertEquals(serialized, json) } @Test fun `kotlin에서 지원하는 jacksonObjectMapper를 사용해보기 역직렬화`(){ val objectMapper = jacksonObjectMapper() val serialized = """ {"name":"Endgame","studio":"Marvel","rating":9.2} """.trimIndent() val actual = objectMapper.readValue<Movie>(serialized) assertEquals(9.2f, actual.rating) }
jacksonObjectMapper를 활용하여 serialized를 수행할 수 있습니다.
jacksonObjectMapper 내부구조
fun jacksonObjectMapper(): ObjectMapper = jsonMapper { addModule(kotlinModule()) }
내부를 보면 kotlinModule이 추가된 것을 볼 수 있고 ObjectMapper가 반환됩니다.
ObjectMapper 테스트
@Test fun `ObjectMapper를 사용해보기`(){ val objectMapper = ObjectMapper() val serialized = """ {"name":"Endgame","studio":"Marvel","rating":9.2} """.trimIndent() val actual = objectMapper.readValue<Movie>(serialized) assertEquals(9.2f, actual.rating) } // com.fasterxml.jackson.databind.exc.InvalidDefinitionException: // Cannot construct instance of `cohttp://m.example.study.KotlinObjectMapperTest$Movie` // (no Creators, like default constructor, exist): cannot deserialize from Object value // no delegate- or property-based Creator)
InvalidDefinitionException이 발생합니다. 기본 생성자가 필요하다는 에러메시지입니다.
ObjectMapper에 kotlin 모듈을 추가하고 테스트
@Test fun `ObjectMapper를 사용해보기`(){ val objectMapper = ObjectMapper() objectMapper.registerModule(kotlinModule()) val serialized = """ {"name":"Endgame","studio":"Marvel","rating":9.2} """.trimIndent() val actual = objectMapper.readValue<Movie>(serialized) assertEquals(9.2f, actual.rating) }
kotlinModule을 추가하고 다시 테스트한다면?
잘 동작합니다.
주의할점
Spring 환경에서 ObjectMapper를 빈으로 등록하게 된다면 Global Bean으로 등록되어 위와 같은 InvalidDefinitionException 예외사항이 발생할 수 있습니다.
이런 경우 내가 작업한 범위 외에서 예외가 발생하기 때문에 원인에 대해 파악하기 힘들었습니다.
참고자료
https://www.baeldung.com/kotlin/jackson-kotlin
'Spring Framework' 카테고리의 다른 글
FeignClient Response로 Http status 제어하기 (0) 2023.12.01 FeignClient DecodeException JsonToken.START_OBJECT (1) 2023.11.27 Spring Boot proxy-target-class 속성 (0) 2023.11.10 Spring Boot Graceful shutdown 동작과정 (0) 2023.11.03 Spring @Transactional의 rollback 동작과정 디버깅 (0) 2023.10.30