Moshi: conceptos clave, biblioteca JSON para Kotlin y cómo funciona

Autor: IT Sectr Publicado: 2026-03-15 Tiempo de lectura: 8 min

Moshi es una biblioteca JSON moderna de Square, creada específicamente para Kotlin y Android teniendo en cuenta las limitaciones de Gson. Es totalmente compatible con la seguridad nula de Kotlin, genera código en tiempo de compilación y no utiliza reflexión, lo que mejora el rendimiento y la fiabilidad. Según Square Moshi, 2024, Moshi proporciona una serialización predecible y admite adaptadores personalizados para cualquier tipo de datos.

Puntos clave

  • Moshi — biblioteca JSON de Square para Kotlin y Android sin reflexión
  • Adaptador Kotlin — soporte integrado para data class, valores predeterminados y seguridad nula
  • @Json — anotación para configurar el nombre del campo e ignorar propiedades
  • Adaptadores — lógica de serialización personalizada mediante @ToJson y @FromJson
  • Generación de código — Moshi genera adaptadores en tiempo de compilación mediante kapt o KSP

Qué es Moshi

Moshi es una biblioteca JSON para JVM, Android y Kotlin Multiplatform, creada por Square (los autores de OkHttp y Retrofit). A diferencia de Gson, Moshi no se basa en la reflexión: los adaptadores se generan en tiempo de compilación mediante la anotación @JsonClass(generateAdapter = true). Esto hace que Moshi sea más rápido, seguro y predecible al trabajar con construcciones específicas de Kotlin.

Filosofía y ventajas

La principal diferencia de Moshi con sus predecesores es el rechazo de la reflexión. La reflexión permite a Gson trabajar con cualquier clase sin preparación, pero el costo es una inicialización lenta, la imposibilidad de optimización por parte del compilador y el riesgo de errores en tiempo de ejecución. Moshi requiere la declaración explícita de clases para la generación de código, pero a cambio ofrece la velocidad del código escrito a mano y una seguridad de tipos completa en tiempo de compilación.

kotlin
// Agregar Moshi a build.gradle
dependencies {
    implementation "com.squareup.moshi:moshi:1.15.0"
    implementation "com.squareup.moshi:moshi-kotlin:1.15.0"
    kapt "com.squareup.moshi:moshi-kotlin-codegen:1.15.0"
}

// Modelo simple con generación de código
@JsonClass(generateAdapter = true)
data class User(
    @Json(name = "user_id")
    val id: Int,
    val name: String,
    val email: String,
    val avatar: String? = null
)

// Uso
val moshi = Moshi.Builder()
    .build()
val jsonAdapter = moshi.adapter(User::class.java)

Instalación y configuración

Para empezar a trabajar con Moshi, es necesario agregar dependencias en build.gradle y anotar los modelos. Moshi.Builder sirve como punto de entrada: a través de él se agregan adaptadores integrados para tipos estándar, adaptadores personalizados y se configura el comportamiento de la biblioteca. Moshi admite adaptadores para Date, Enum, Collection y Map de forma nativa, pero las clases de Kotlin requieren el módulo moshi-kotlin. A diferencia de Gson, Moshi no utiliza reflexión para las clases de Kotlin por defecto: para esto se conecta KotlinJsonAdapterFactory, que sirve como alternativa cuando no se usa la generación de código o la clase no está anotada con @JsonClass. Este enfoque garantiza que el desarrollador elija explícitamente entre el rendimiento de la generación de código y la flexibilidad de la reflexión para cada clase específica.

Creación de Moshi y adición de adaptadores

Después de construir Moshi a través de Builder, el desarrollador obtiene una instancia de Moshi y solicita un adaptador para la clase deseada. JsonAdapter es el objeto central que realiza la serialización mediante toJson() y la deserialización mediante fromJson(). Moshi utiliza automáticamente el adaptador generado si la clase está anotada con @JsonClass(generateAdapter = true), de lo contrario aplica KotlinJsonAdapterFactory reflexivo como alternativa. Este enfoque combina la velocidad de la generación de código con la flexibilidad de un mecanismo reflexivo para proyectos de cualquier escala y complejidad. Moshi es adecuado tanto para aplicaciones pequeñas como para grandes proyectos empresariales con cientos de modelos de datos.

kotlin
// Configurar Moshi con KotlinJsonAdapterFactory
val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .add(LocalDateAdapter())
    .build()

// Usar el adaptador
val adapter = moshi.adapter(User::class.java)

// Serialización
val user = User(1, "Alice", "alice@test.com")
val json = adapter.toJson(user)

// Deserialización
val jsonString = """{"user_id":2,"name":"Bob","email":"bob@test.com"}"""
val parsedUser = adapter.fromJson(jsonString)

// Trabajar con listas
val listAdapter = moshi.adapter(
    Types.newParameterizedType(
        List::class.java,
        User::class.java
    )
)

Anotaciones y adaptadores

Moshi utiliza anotaciones para configurar la serialización y admitir tipos personalizados. @Json(name = "...") establece la clave JSON para un campo. @Transient excluye un campo de la serialización. @JsonClass(generateAdapter = true) habilita la generación de código. Para lógica personalizada, Moshi proporciona las anotaciones @ToJson y @FromJson, que se pueden colocar en una clase adaptadora separada.

@Json y adaptadores personalizados

La anotación @Json reemplaza a @SerializedName de Gson y funciona de manera similar: el campo kotlinName se asocia con la clave JSON "kotlin_name". Para tipos que Moshi no puede serializar por defecto (por ejemplo, LocalDate), el desarrollador crea una clase con métodos @ToJson y @FromJson. Los adaptadores se registran mediante Moshi.Builder.add() y se aplican globalmente o a un tipo específico. Moshi admite clases selladas y serialización polimórfica mediante @JsonClass con un discriminador explícito, lo que permite trabajar con jerarquías de tipos en JSON sin necesidad de verificación manual de campos. Durante la deserialización, Moshi ignora las claves JSON desconocidas por defecto, lo que garantiza la compatibilidad hacia atrás al agregar nuevos campos en el servidor sin cambiar el código del cliente. Para depuración, se puede habilitar el modo estricto mediante failOnUnknown, que lanza una excepción cuando se encuentran claves desconocidas.

kotlin
// Adaptador personalizado para LocalDate
class LocalDateAdapter {

    @ToJson
    fun toJson(date: LocalDate): String {
        return date.format(DateTimeFormatter.ISO_LOCAL_DATE)
    }

    @FromJson
    fun fromJson(dateString: String): LocalDate {
        return LocalDate.parse(dateString)
    }
}

// Modelo con anotaciones de Moshi
@JsonClass(generateAdapter = true)
data class Event(
    @Json(name = "event_id")
    val id: Int,

    @Json(name = "event_date")
    val date: LocalDate,

    @Transient
    val localCache: String? = null
)

// Registrar el adaptador
val moshi = Moshi.Builder()
    .add(LocalDateAdapter())
    .add(KotlinJsonAdapterFactory())
    .build()

Moshi vs Gson

Comparar Moshi y Gson es una pregunta frecuente al elegir una biblioteca JSON para un proyecto Android. Moshi gana en el desarrollo moderno de Kotlin gracias a la generación de código, la seguridad nula y la velocidad. Gson sigue siendo relevante para proyectos Java, código heredado y escenarios donde la configuración mínima es importante. La diferencia se nota con grandes volúmenes de datos y modelos complejos.

Rendimiento y seguridad

Las pruebas de rendimiento muestran que Moshi con generación de código es 2–5 veces más rápido que Gson en operaciones de serialización y deserialización. La ventaja clave de Moshi es el manejo correcto de la seguridad nula de Kotlin: si falta un campo en JSON y el modelo lo declara como no nulo sin valor predeterminado, Moshi lanza una excepción en tiempo de deserialización, evitando errores ocultos.

CaracterísticaGsonMoshi
Mecanismoreflexióngeneración de código / reflexión
Seguridad nulano la considerasoporte completo de Kotlin
Velocidadmediaalta
Valores predeterminadosno los admitelos admite
Kotlin Multiplatformno
Tamaño de biblioteca~240 Kb~150 Kb

La elección entre Moshi y Gson depende del contexto del proyecto. Los nuevos proyectos en Kotlin se benefician de Moshi gracias a la seguridad de tipos y el rendimiento. Gson sigue siendo una opción razonable para soportar código Java, estructuras JSON dinámicas o cuando la simplicidad de configuración es más importante que la velocidad. Para Kotlin Multiplatform, Moshi es la única de las dos opciones que admite esta plataforma.

Al migrar de Gson a Moshi, los principales cambios afectan a las anotaciones y adaptadores. @SerializedName de Gson se reemplaza con @Json(name = "..."), y los JsonSerializer/JsonDeserializer personalizados con el par @ToJson/@FromJson. Para modelos con valores predeterminados y campos anulables, Moshi se comporta de manera más predecible: si falta un campo no nulo sin valor predeterminado en JSON, Moshi lanza JsonDataException, evitando NPE ocultos. La integración con Retrofit a través de MoshiConverterFactory se agrega con una sola dependencia y no requiere cambiar la arquitectura de la capa de red. Para la ofuscación mediante ProGuard o R8, es necesario agregar reglas para conservar las clases anotadas con @JsonClass y los adaptadores generados, de lo contrario la serialización se romperá en la compilación de lanzamiento. En general, la migración de Gson a Moshi está justificada en nuevos proyectos Kotlin donde el rendimiento y la seguridad de tipos son importantes.

kotlin
// Comparación de serialización: Gson vs Moshi
data class Sample(
    val name: String,
    val count: Int,
    val tags: List<String> = listOf()
)

// Gson: funciona mediante reflexión
val gson = Gson()
val fromGson = gson.fromJson("""{"name":"test"}""",
    Sample::class.java)
// count = 0 (predeterminado), pero la seguridad nula no se verifica

// Moshi: requiere un adaptador, la seguridad nula es explícita
@JsonClass(generateAdapter = true)
data class SampleMoshi(
    val name: String,
    val count: Int,
    val tags: List<String> = listOf()
)

Preguntas frecuentes

¿Qué es Moshi en Android?

Moshi es una biblioteca JSON de Square para Kotlin y Android que utiliza generación de código en lugar de reflexión. Proporciona alto rendimiento, manejo correcto de la seguridad nula de Kotlin y compatibilidad con Kotlin Multiplatform.

¿En qué es mejor Moshi que Gson?

Moshi supera a Gson en velocidad (2–5 veces más rápido gracias a la generación de código), seguridad (respeta las anotaciones nulas de Kotlin) y tamaño (~90 Kb más pequeño). Moshi también admite Kotlin Multiplatform y valores predeterminados en data class.

¿Cómo funciona la anotación @JsonClass en Moshi?

@JsonClass(generateAdapter = true) indica a Moshi que genere un adaptador para la clase dada en tiempo de compilación. El adaptador generado realiza la serialización directamente, sin reflexión, lo que proporciona el máximo rendimiento.

¿Cómo crear un adaptador personalizado de Moshi?

Cree una clase con métodos anotados con @ToJson (serialización) y @FromJson (deserialización). Registre la instancia mediante Moshi.Builder.add(). Moshi encontrará y aplicará automáticamente el adaptador al trabajar con el tipo correspondiente.

¿Moshi admite Kotlin Multiplatform?

Sí, Moshi admite Kotlin Multiplatform a partir de la versión 1.13.0. Esto lo convierte en la única solución JSON popular para proyectos KMP, permitiendo usar código de serialización común en todas las plataformas objetivo.

Resumen

  • Moshi — biblioteca JSON moderna de Square con generación de código en lugar de reflexión
  • @JsonClass — anotación para generar adaptadores, ofreciendo velocidad de código escrito a mano
  • @Json — configuración de claves JSON, @Transient — exclusión de campos de la serialización
  • @ToJson y @FromJson — API simple para adaptadores personalizados de cualquier tipo
  • Seguridad nula — Moshi respeta las anotaciones de Kotlin y lanza una excepción en caso de discrepancia
  • Rendimiento — 2–5 veces más rápido que Gson en operaciones de serialización y deserialización
  • Kotlin Multiplatform — soporte KMP para código de serialización universal

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también