Как использовать джексон для десериализации в коллекциях Котлина

Пример кода, который я хочу:

data class D(val a: String, val b: Int) val jsonStr = """[{"a": "value1", "b": 1}, {"a": "value2", "b":"2}]""" // what I need val listOfD: List<D> = jacksonObjectMapper().whatMethodAndParameter? 

С текущими версиями модуля Jackson Kotlin Module, если вы импортируете полный пакет модулей или определенную функцию расширения, у вас будут все доступные методы расширения. Такие как:

 import com.fasterxml.jackson.module.kotlin.* val JSON = jacksonObjectMapper() // keep around and re-use val myList: List<String> = JSON.readValue("""["a","b","c"]""") 

Поэтому модуль Jackson для Kotlin выведет правильный тип и вам не нужен экземпляр TypeReference .

поэтому ваш случай (слегка переименованный и исправленный класс данных и JSON):

 import com.fasterxml.jackson.module.kotlin.readValue data class MyData(val a: String, val b: Int) val JSON = jacksonObjectMapper() val jsonStr = """[{"a": "value1", "b": 1}, {"a": "value2", "b": 2}]""" val myList: List<MyData> = JSON.readValue(jsonStr) 

Вы также можете использовать форму:

 val myList = JSON.readValue<List<MyData>>(jsonStr) 

Без импорта у вас будет ошибка, потому что функция расширения не найдена.

TL; DR

С Jackson 2.6.3-2 делать так, как @ jason-minard советует и просто использует:

 import com.fasterxml.jackson.module.kotlin.readValue val listOfD: List<D> = jacksonMapper.readValue(jsonStr) 

Детали

В Kotlin нет ничего особенного для десериализации коллекций , хотя вам понадобится модуль kotlin jackson для десериализации классов данных без аннотаций.

А именно, для того, чтобы отслеживать общий параметр списка ( D ), в вашем случае потребуется полная информация типа типа reified. в противном случае (например, если вы используете readValue(jsonStr, List::class.java) ), Джексон будет видеть это только как стертый тип (то есть List ) (как Kotlin делает явным) и десериализовать его в List<Map<String, String>> , не зная, что он должен построить D s. Это выполняется с помощью анонимного подкласса TypeReference на Java, чтобы Джексон мог получить доступ к полному типу reified для десериализации во время выполнения.

Перевод кода Джексона Java буквально в Kotlin, таким образом достигается то, что вы хотите (и, как прокомментировал @eski, обратите внимание, что JSON в вашем примере недействителен):

 val jacksonMapper = ObjectMapper().registerModule(KotlinModule()) val jsonStr = """[{"a": "value1", "b": 1}, {"a": "value2", "b":2}]""" val listOfD: List<D> = jacksonMapper.readValue(jsonStr, object : TypeReference<List<D>>(){}) assertEquals(listOf(D("value1", 1), D("value2", 2)), listOfD) 

Это немного подробный и уродливый, поэтому вы можете скрыть его в функции Kotlin (расширение) (особенно если вы планируете использовать его несколько раз):

 inline fun <reified T> ObjectMapper.readValue(json: String): T = readValue(json, object : TypeReference<T>(){}) 

который позволит вам просто позвонить:

 val listOfD: List<D> = jacksonMapper.readValue(jsonStr) 

И это только то, что включено в модуль 2.6.3-2 Kotlin.