Trabajo con JSON en Kotlin: guía completa de parsing y serialización
JSON (JavaScript Object Notation) sigue siendo uno de los formatos de intercambio de datos más populares en el desarrollo web moderno. Al trabajar con Kotlin, ya sea en el backend con Ktor o en una aplicación móvil para Android, saber cómo parsear y serializar JSON de manera eficiente es una habilidad obligatoria. En este artículo analizaremos tres enfoques principales para trabajar con JSON en Kotlin: el uso de las bibliotecas Gson, Moshi y la solución oficial de JetBrains — kotlinx.serialization.
¿Por qué Kotlin requiere un enfoque especial para JSON?
Kotlin es un lenguaje de tipado estático con características como null-safety, data classes y propiedades por defecto. Las bibliotecas para trabajar con JSON deben tener en cuenta estas características para que el código no solo sea funcional, sino también idiomático. Una configuración incorrecta puede provocar NullPointerException o un comportamiento inesperado durante la deserialización.
1. Uso de Gson para trabajar con JSON
Gson de Google es una de las bibliotecas más antiguas y extendidas. Es sencilla de usar, pero tiene algunas particularidades al trabajar con Kotlin.
Conexión de la dependencia
// build.gradle.ktsimplementation("com.google.code.gson:gson:2.10.1")Serialización de un objeto a JSON
import com.google.gson.Gson
data class User( val id: Int, val name: String, val email: String? = null)
fun main() { val user = User(1, "Iván Petrov", "ivan@example.com") val gson = Gson() val json = gson.toJson(user) println(json) // Salida: {"id":1,"name":"Iván Petrov","email":"ivan@example.com"}}Parsing de JSON a objeto
fun parseUser(jsonString: String): User { val gson = Gson() return gson.fromJson(jsonString, User::class.java)}
fun main() { val json = """{"id":2,"name":"Ana Smirnova","email":null}""" val user = parseUser(json) println(user.name) // Ana Smirnova}Importante: Gson utiliza la reflexión de Java y puede no tener en cuenta la null-safety de Kotlin. Durante la deserialización, los campos declarados como non-null pueden recibir un valor null, lo que provocará un error en tiempo de ejecución. Se recomienda usar @JvmOverloads y constructores con valores por defecto.
2. Moshi — alternativa moderna de Square
Moshi fue creado teniendo en cuenta las particularidades de Kotlin y ofrece una mejor integración con la null-safety y las data classes.
Conexión de la dependencia
// build.gradle.ktsimplementation("com.squareup.moshi:moshi-kotlin:1.15.0")kapt("com.squareup.moshi:moshi-kotlin-codegen:1.15.0")Ejemplo de trabajo con Moshi
import com.squareup.moshi.Moshiimport com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
data class Product( val id: Int, val title: String, val price: Double, val inStock: Boolean = false)
fun main() { val moshi = Moshi.Builder() .addLast(KotlinJsonAdapterFactory()) .build()
val adapter = moshi.adapter(Product::class.java)
// Serialización val product = Product(101, "Portátil", 89999.99, true) val json = adapter.toJson(product) println(json) // {"id":101,"title":"Portátil","price":89999.99,"inStock":true}
// Deserialización val jsonString = """{"id":102,"title":"Ratón","price":2500.00}""" val parsedProduct = adapter.fromJson(jsonString) println(parsedProduct?.title) // Ratón println(parsedProduct?.inStock) // false (valor por defecto)}Moshi maneja automáticamente los valores por defecto en las data classes y funciona correctamente con tipos nullable. Para un mejor rendimiento, se recomienda usar la generación de código mediante la anotación @JsonClass.