Moshi: concepte cheie, biblioteca JSON Kotlin și cum funcționează

Autor: IT Sectr Publicat: 2026-03-15 Timp de citire: 8 min

Moshi este o bibliotecă JSON modernă de la Square, creată special pentru Kotlin și Android ținând cont de limitările Gson. Este complet compatibilă cu null-safety din Kotlin, generează cod în faza de compilare și nu utilizează reflexie, ceea ce crește performanța și fiabilitatea. Conform datelor Square Moshi, 2024, Moshi asigură serializare predictibilă și suportă adaptoare personalizate pentru orice tipuri de date.

Principalele puncte

  • Moshi — bibliotecă JSON de la Square pentru Kotlin și Android fără reflexie
  • Adaptor Kotlin — suport încorporat pentru data class, valori implicite și null safety
  • @Json — adnotare pentru configurarea numelui câmpului și ignorarea proprietăților
  • Adaptoare — logică de serializare personalizată prin @ToJson și @FromJson
  • Generare de cod — Moshi generează adaptoare în faza de compilare prin kapt sau KSP

Ce este Moshi

Moshi este o bibliotecă JSON pentru JVM, Android și Kotlin Multiplatform, creată de Square (autorii OkHttp și Retrofit). Spre deosebire de Gson, Moshi nu se bazează pe reflexie — adaptoarele sunt generate în faza de compilare prin adnotarea @JsonClass(generateAdapter = true). Acest lucru face Moshi mai rapid, mai sigur și mai predictibil în lucrul cu construcții specifice Kotlin.

Filozofia și avantajele

Principala diferență a Moshi față de predecesori este renunțarea la reflexie. Reflexia permite Gson să lucreze cu orice clasă fără pregătire, dar prețul este inițializarea lentă, imposibilitatea optimizării de către compilator și riscul de erori în timpul execuției. Moshi necesită indicarea explicită a claselor pentru generarea de cod, dar în schimb oferă viteza codului scris manual și siguranța completă a tipurilor în faza de compilare.

kotlin
// Conectarea Moshi în 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"
}

// Model simplu cu generare de cod
@JsonClass(generateAdapter = true)
data class User(
    @Json(name = "user_id")
    val id: Int,
    val name: String,
    val email: String,
    val avatar: String? = null
)

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

Instalare și configurare

Pentru a începe lucrul cu Moshi, trebuie adăugate dependințele în build.gradle și adnotate modelele. Moshi.Builder servește ca punct de intrare: prin el se adaugă adaptoare încorporate pentru tipuri standard, adaptoare personalizate și se configurează comportamentul bibliotecii. Moshi suportă adaptoare pentru Date, Enum, Collection și Map din cutie, dar pentru clasele Kotlin este necesar modulul moshi-kotlin. Spre deosebire de Gson, Moshi nu utilizează reflexia pentru clasele Kotlin implicit — pentru aceasta se conectează KotlinJsonAdapterFactory, care servește ca opțiune de rezervă când generarea de cod nu este aplicată sau clasa nu este adnotată cu @JsonClass. Această abordare garantează că dezvoltatorul alege explicit între performanța generării de cod și flexibilitatea reflexiei pentru fiecare clasă în parte.

Crearea Moshi și adăugarea adaptoarelor

După construirea Moshi prin Builder, dezvoltatorul obține o instanță Moshi și solicită un adaptor pentru clasa dorită. JsonAdapter este obiectul central care execută serializarea prin toJson() și deserializarea prin fromJson(). Moshi utilizează automat adaptorul generat dacă clasa este adnotată cu @JsonClass(generateAdapter = true), altfel aplică KotlinJsonAdapterFactory reflexiv ca opțiune de rezervă. Această abordare combină viteza generării de cod cu flexibilitatea mecanismului reflexiv pentru proiecte de orice scară și nivel de complexitate. Moshi este potrivit atât pentru aplicații mici, cât și pentru proiecte corporative mari cu sute de modele de date.

kotlin
// Configurarea Moshi cu KotlinJsonAdapterFactory
val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .add(LocalDateAdapter())
    .build()

// Utilizarea adaptorului
val adapter = moshi.adapter(User::class.java)

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

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

// Lucrul cu lista
val listAdapter = moshi.adapter(
    Types.newParameterizedType(
        List::class.java,
        User::class.java
    )
)

Adnotări și adaptoare

Moshi utilizează adnotări pentru configurarea serializării și suportul tipurilor personalizate. @Json(name = "...") setează cheia JSON pentru câmp. @Transient exclude câmpul din serializare. @JsonClass(generateAdapter = true) activează generarea de cod. Pentru logică personalizată, Moshi oferă adnotările @ToJson și @FromJson, care pot fi plasate într-o clasă de adaptor separată.

@Json și adaptoare personalizate

Adnotarea @Json înlocuiește @SerializedName din Gson și funcționează similar: câmpul kotlinName este legat de cheia JSON „kotlin_name". Pentru tipurile pe care Moshi nu le poate serializa implicit (de exemplu, LocalDate), dezvoltatorul creează o clasă cu metode @ToJson și @FromJson. Adaptoarele se înregistrează prin Moshi.Builder.add() și se aplică global sau pentru un tip specific. Moshi suportă sealed class și serializarea polimorfă prin @JsonClass cu indicarea explicită a discriminatorului, ceea ce permite lucrul cu ierarhii de tipuri în JSON fără verificarea manuală a câmpurilor. La deserializare, Moshi ignoră implicit cheile necunoscute în JSON, ceea ce asigură compatibilitatea inversă la adăugarea de noi câmpuri pe partea serverului fără modificarea codului client. Pentru depanare se poate activa modul strict prin failOnUnknown, care aruncă o excepție la detectarea cheilor necunoscute.

kotlin
// Adaptor personalizat pentru 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)
    }
}

// Model cu adnotări 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
)

// Înregistrarea adaptorului
val moshi = Moshi.Builder()
    .add(LocalDateAdapter())
    .add(KotlinJsonAdapterFactory())
    .build()

Moshi vs Gson

Compararea Moshi și Gson este o întrebare frecventă la alegerea unei biblioteci JSON pentru un proiect Android. Moshi câștigă în dezvoltarea modernă Kotlin datorită generării de cod, null-safety și vitezei. Gson rămâne relevant pentru proiecte Java, cod moștenit și scenarii unde configurația minimă este importantă. Diferența devine vizibilă la volume mari de date și modele complexe.

Performanță și siguranță

Testele de performanță arată că Moshi cu generare de cod funcționează de 2-5 ori mai rapid decât Gson la operațiile de serializare și deserializare. Avantajul cheie al Moshi este gestionarea corectă a null-safety din Kotlin: dacă un câmp lipsește în JSON, iar în model este declarat ca non-null fără valoare implicită, Moshi aruncă o excepție în faza de deserializare, prevenind erorile ascunse.

CaracteristicăGsonMoshi
Mecanismreflexiegenerare de cod / reflexie
Null safetynu ia în consideraresuport complet Kotlin
Vitezămediemare
Valori implicitenu suportăsuportă
Kotlin Multiplatformnuda
Dimensiune bibliotecă~240 Kb~150 Kb

Alegerea între Moshi și Gson depinde de contextul proiectului. Proiectele noi pe Kotlin beneficiază de Moshi datorită siguranței tipurilor și performanței. Gson rămâne o alegere rezonabilă pentru suportul codului Java, structuri JSON dinamice sau când simplitatea conectării este mai importantă decât viteza. Pentru Kotlin Multiplatform, Moshi este singurul dintre cele două variante care suportă această platformă.

La migrarea de la Gson la Moshi, modificările principale privesc adnotările și adaptoarele. @SerializedName din Gson se înlocuiește cu @Json(name = "..."), iar JsonSerializer/JsonDeserializer personalizate — cu perechea @ToJson/@FromJson. Pentru modelele cu valori implicite și câmpuri nullable, Moshi se comportă mai predictibil: dacă în JSON lipsește un câmp non-null fără valoare implicită, Moshi aruncă JsonDataException, prevenind NPE ascunse. Integrarea cu Retrofit prin MoshiConverterFactory se adaugă cu o singură dependență și nu necesită modificarea arhitecturii stratului de rețea. Pentru ofuscarea prin ProGuard sau R8 trebuie adăugate reguli de păstrare a claselor adnotate cu @JsonClass și a adaptoarelor generate, altfel serializarea se va strica în versiunea release. În general, migrarea de la Gson la Moshi este justificată în proiecte noi Kotlin unde performanța și siguranța tipurilor sunt importante.

kotlin
// Compararea serializării: Gson vs Moshi
data class Sample(
    val name: String,
    val count: Int,
    val tags: List<String> = listOf()
)

// Gson: funcționează prin reflexie
val gson = Gson()
val fromGson = gson.fromJson("""{"name":"test"}""",
    Sample::class.java)
// count = 0 (default), dar null-safety nu este verificat

// Moshi: necesită adaptor, null-safety este explicit
@JsonClass(generateAdapter = true)
data class SampleMoshi(
    val name: String,
    val count: Int,
    val tags: List<String> = listOf()
)

Întrebări frecvente

Ce este Moshi în Android?

Moshi este o bibliotecă JSON de la Square pentru Kotlin și Android, care utilizează generarea de cod în locul reflexiei. Asigură performanță ridicată, gestionarea corectă a null-safety din Kotlin și compatibilitate cu Kotlin Multiplatform.

Cu ce este Moshi mai bun decât Gson?

Moshi întrece Gson în viteză (de 2-5 ori mai rapid datorită generării de cod), siguranță (ia în considerare adnotările null din Kotlin) și dimensiune (mai mic cu ~90 Kb). Moshi suportă de asemenea Kotlin Multiplatform și valori implicite în data class.

Cum funcționează adnotarea @JsonClass în Moshi?

@JsonClass(generateAdapter = true) indică Moshi să genereze un adaptor pentru această clasă în faza de compilare. Adaptorul generat execută serializarea direct, fără reflexie, oferind performanță maximă.

Cum se creează un adaptor personalizat Moshi?

Creați o clasă cu metode adnotate cu @ToJson (serializare) și @FromJson (deserializare). Înregistrați instanța prin Moshi.Builder.add(). Moshi va găsi și aplica automat adaptorul la lucrul cu tipul corespunzător.

Suportă Moshi Kotlin Multiplatform?

Da, Moshi suportă Kotlin Multiplatform începând cu versiunea 1.13.0. Acest lucru îl face singura soluție JSON populară pentru proiecte KMP, permițând utilizarea codului comun de serializare pe toate platformele țintă.

Concluzii

  • Moshi — bibliotecă JSON modernă de la Square cu generare de cod în loc de reflexie
  • @JsonClass — adnotare pentru generarea adaptorului, asigurând viteza codului scris manual
  • @Json — configurarea cheilor JSON, @Transient — excluderea câmpurilor din serializare
  • @ToJson și @FromJson — API simplu pentru adaptoare personalizate de orice tip
  • Null safety — Moshi ia în considerare adnotările Kotlin și aruncă excepție la nepotrivire
  • Performanță — de 2-5 ori mai rapid decât Gson la operațiile de serializare și deserializare
  • Kotlin Multiplatform — suport KMP pentru cod de serializare universal

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și