개요

ObjectMapper 이용, readValue 로 List 변환 시 자주 헷갈림. 

 

코드

/**
 * https://kotlinlang.org/docs/object-declarations.html
 *
 * - object 키워드를 파라미터 내에 선언함으로써, 익명클래스 효과를 누릴 수 있음
 * - 일회용으로 유용함
 * - 기존 클래스를 상속하거나 인터페이스 구현을 할 수 있음
 * - 익명 클래스의 인스턴스는 이름이 아닌 표현식으로 정의되기 때문에 익명 오브젝트라고 불리기도 함
 */
class ReadValueTest {

    private val mapper = ObjectMapper().registerKotlinModule()

    @Test
    @DisplayName("json 을 리스트로 반환한다.")
    fun readValueToListTest() {

        // given

        // when
        val coffeeDtos = mapper.readValue(json, object: TypeReference<List<CoffeeDto>>() {})

        // then
        coffeeDtos.size shouldBe 3
        coffeeDtos[0].name shouldBe "coffee1"
        coffeeDtos[1].name shouldBe "coffee2"
        coffeeDtos[2].name shouldBe "coffee3"
    }
}

data class CoffeeDto(
    val name: String
)

val json = """
    [
        {
            "name": "coffee1"
        },
        {
            "name": "coffee2"
        },
        {
            "name": "coffee3"
        }
    ]
""".trimIndent()
inline fun <reified T: Any> T.toJson(): String = mapper.writeValueAsString(this)
inline fun <reified T: Any> String.toObject(): T = mapper.readValue(this, T::class.java)
inline fun <reified T: Any> String.toList(): List<T> = mapper.readValue(this, object: TypeReference<List<T>>() {})

toObject<List<Any>> 형태로 쓰게되면, List 안에 요소가 LinkedHashMap 의 형태로 나온다.

toObject 는 단일 클래스, List<Any> 타입으로 변환하고자 한다면 toList() 를 사용하도록 한다.

 

(2025-05-26 수정)

toList() 사용 시, 매번 익명클래스를 작성해야 하는 번거로움이 생긴다.

이 방식보단 readerForList() 를 이용하면 코드를 간결하게 작성할 수 있다.

inline fun <reified T : Any> String?.toObjectList(): List<T> = this?.let { mapper.readerForListOf(T::class.java).readValue(it) } ?: emptyList()

 

결과내용

class JacksonTest {
    @Test
    fun `coffeeDto 를 변환, deserialize 한다`() {
        

        val json = """
            [{"name":"아메리카노4"},{"name":"아메리카노5"},{"name":"아메리카노6"}]
        """.trimIndent()

        val coffeeDtos = json.toObjectList<CoffeeDto>()
        println(coffeeDtos)
        println(coffeeDtos.first().name)
    }
}

// [CoffeeDto(name=아메리카노4), CoffeeDto(name=아메리카노5), CoffeeDto(name=아메리카노6)]
// 아메리카노4
Posted by doubler
,