ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Kotlin ObjectMapper 주의사항
    Spring Framework 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

     

    댓글

Designed by Tistory.