Spring Framework

Kotlin ObjectMapper 주의사항

Junuuu 2023. 11. 14. 00:01

개요

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