Cómo usar jackson para deserializar las collections de Kotlin

Código de muestra lo que quiero:

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? 

Con las versiones actuales del Módulo Jackson Kotlin, si importa el package de module completo o la function de extensión específica, tendrá todos los methods de extensión disponibles. Como:

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

Por lo tanto, el Módulo Jackson para Kotlin deducirá el tipo correcto y no necesita una instancia de TypeReference .

por lo que su caso (ligeramente renombrado y corregido la class de datos, y 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) 

También puedes usar el formulario:

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

Sin la import, tendrá un error porque no se encuentra la function de extensión.

TL; DR

Con Jackson 2.6.3-2 haga lo que @ jason-minard aconseja y simplemente use:

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

Detalles

No hay nada especial acerca de Kotlin wrt en deserializar collections , aunque necesitará el module kotlin jackson para deserializar classs de datos sin annotations.

A saber, requerirá información completa del tipo reificado en su caso para poder seguir el parámetro genérico de la list ( D ); de lo contrario (por ejemplo, si usa readValue(jsonStr, List::class.java) ) Jackson solo lo verá como un tipo borrado (es decir, List ) (como lo hace explícito Kotlin) y lo deserializará a List<Map<String, String>> , sin saber que tiene que build D s. Esto se TypeReference utilizando una subclass anónima de TypeReference en Java para que Jackson pueda acceder al tipo completo reificado para deserializar en time de ejecución.

Traduciendo el código de Jackson Java literalmente a Kotlin, lo siguiente logra lo que quieres (y como comentó @eski, ten en count que el JSON en tu ejemplo no es válido):

 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) 

Sin embargo, esto es un poco detallado y feo, por lo que podría ocultarlo en una function Kotlin (extensión) (especialmente si planea usarla varias veces):

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

que le permitiría entonces simplemente llamar:

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

Y esto es lo que está incluido en el module 2.6.3-2 jackson Kotlin.

  • Swift si lo dejas y más en Kotlin
  • ¿Cómo henetworkingo la documentation de KDoc?
  • Operador condicional terciario de Kotlin
  • No se puede resolver el host pokeAPI
  • Cuál es la diferencia entre la class normal y la class de datos en kotlin
  • Kotlin: No se puede usar GenericTypeIndicator para llamar al getValue de Firebase Database
  • App build.gradle.kts Archivo sin resolver Erros de reference
  • ¿Es posible usar funciones de order superior con arguments opcionales?
  • Genéricos para RecyclerView.Adapter Android
  • Cómo anotar una columna como NOT NULL utilizando Android Room Persistence Library
  • kotlin: no se puede get la anotación de api de validation