A Moshi egy modern JSON könyvtár a Square-től, amelyet kifejezetten Kotlin és Android számára hoztak létre, figyelembe véve a Gson korlátait. Teljesen kompatibilis a Kotlin null-biztonságával, kódot generál a fordítási fázisban és nem használ reflexiót, ami növeli a teljesítményt és a megbízhatóságot. A Square Moshi, 2024 adatai szerint a Moshi kiszámítható szerializációt biztosít és támogatja az egyedi adaptereket bármilyen adattípushoz.
Főbb pontok
Moshi egy JSON könyvtár JVM, Android és Kotlin Multiplatform számára, amelyet a Square (az OkHttp és Retrofit alkotói) hozott létre. A Gson-tól eltérően a Moshi nem támaszkodik reflexióra — az adapterek a fordítási fázisban jönnek létre a @JsonClass(generateAdapter = true) annotáció segítségével. Ez teszi a Moshi-t gyorsabbá, biztonságosabbá és kiszámíthatóbbá a Kotlin-specifikus konstrukciókkal való munka során.
A Moshi fő különbsége elődeihez képest a reflexió elutasítása. Reflexió lehetővé teszi a Gson számára, hogy előkészület nélkül dolgozzon bármely osztállyal, de ennek ára a lassú inicializálás, a fordító általi optimalizálás lehetetlensége és a futásidejű hibák kockázata. A Moshi explicit osztályok megadását igényli a kódgeneráláshoz, de cserébe a kézzel írt kód sebességét és teljes típusbiztonságot ad a fordítási fázisban.
// Moshi csatlakoztatása build.gradle-ben
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"
}
// Egyszerű modell kódgenerálással
@JsonClass(generateAdapter = true)
data class User(
@Json(name = "user_id")
val id: Int,
val name: String,
val email: String,
val avatar: String? = null
)
// Használat
val moshi = Moshi.Builder()
.build()
val jsonAdapter = moshi.adapter(User::class.java)
A Moshi-val való munka megkezdéséhez hozzá kell adni a függőségeket a build.gradle-ben és annotálni kell a modelleket. Moshi.Builder belépési pontként szolgál: rajta keresztül adjuk hozzá a beépített adaptereket a szabványos típusokhoz, az egyedi adaptereket, és konfiguráljuk a könyvtár viselkedését. A Moshi támogatja a Date, Enum, Collection és Map adaptereket dobozból, de a Kotlin osztályokhoz a moshi-kotlin modul szükséges. A Gson-tól eltérően a Moshi alapértelmezetten nem használ reflexiót a Kotlin osztályokhoz — ehhez a KotlinJsonAdapterFactory csatlakozik, amely tartalék opcióként szolgál, amikor a kódgenerálás nem alkalmazható vagy az osztály nincs @JsonClass annotációval ellátva. Ez a megközelítés garantálja, hogy a fejlesztő explicit módon választ a kódgenerálás teljesítménye és a reflexió rugalmassága között minden egyes osztály esetében.
A Moshi Builder segítségével történő felépítése után a fejlesztő kap egy Moshi példányt és adaptert kér a kívánt osztályhoz. JsonAdapter a központi objektum, amely a toJson() segítségével szerializációt és a fromJson() segítségével deszerializációt végez. A Moshi automatikusan használja a generált adaptert, ha az osztály @JsonClass(generateAdapter = true) annotációval van ellátva, ellenkező esetben a reflektív KotlinJsonAdapterFactory-t alkalmazza tartalék opcióként. Ez a megközelítés ötvözi a kódgenerálás sebességét a reflektív mechanizmus rugalmasságával bármilyen méretű és összetettségű projekt esetén. A Moshi kiválóan alkalmas mind kis alkalmazásokhoz, mind nagyvállalati projektekhez, amelyek több száz adatmodellel rendelkeznek.
// Moshi konfigurálása KotlinJsonAdapterFactory-val
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.add(LocalDateAdapter())
.build()
// Adapter használata
val adapter = moshi.adapter(User::class.java)
// Szerializáció
val user = User(1, "Alice", "alice@test.com")
val json = adapter.toJson(user)
// Deszerializáció
val jsonString = """{"user_id":2,"name":"Bob","email":"bob@test.com"}"""
val parsedUser = adapter.fromJson(jsonString)
// Munka listával
val listAdapter = moshi.adapter(
Types.newParameterizedType(
List::class.java,
User::class.java
)
)
Moshi annotációkat használ a szerializáció konfigurálásához és az egyedi típusok támogatásához. A @Json(name = "...") beállítja a JSON kulcsot a mezőhöz. A @Transient kizárja a mezőt a szerializációból. A @JsonClass(generateAdapter = true) bekapcsolja a kódgenerálást. Az egyedi logikához a Moshi a @ToJson és @FromJson annotációkat biztosítja, amelyek egy külön adapter osztályba helyezhetők.
A @Json annotáció helyettesíti a Gson @SerializedName-jét és hasonlóan működik: a kotlinName mező a „kotlin_name“ JSON kulcshoz kapcsolódik. Azon típusok esetében, amelyeket a Moshi alapértelmezetten nem tud szerializálni (pl. LocalDate), a fejlesztő létrehoz egy osztályt @ToJson és @FromJson metódusokkal. Adapterek a Moshi.Builder.add() segítségével regisztrálhatók és globálisan vagy egy adott típusra alkalmazhatók. A Moshi támogatja a sealed class és a polimorf szerializációt a @JsonClass segítségével diszkriminátor explicit megadásával, ami lehetővé teszi a típushierarchiákkal való munkát JSON-ban kézi mezőellenőrzés nélkül. Deszerializációkor a Moshi alapértelmezetten figyelmen kívül hagyja az ismeretlen kulcsokat a JSON-ban, ami visszafelé kompatibilitást biztosít új mezők szerveroldali hozzáadásakor a klienskód módosítása nélkül. Hibakereséshez a szigorú mód a failOnUnknown segítségével aktiválható, amely kivételt dob ismeretlen kulcsok észlelésekor.
// Egyedi adapter LocalDate-hez
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)
}
}
// Modell Moshi annotációkkal
@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
)
// Adapter regisztrálása
val moshi = Moshi.Builder()
.add(LocalDateAdapter())
.add(KotlinJsonAdapterFactory())
.build()
A Moshi és Gson összehasonlítása gyakori kérdés a JSON könyvtár kiválasztásakor egy Android projekthez. Moshi nyer a modern Kotlin fejlesztésben a kódgenerálás, null-biztonság és sebesség révén. A Gson továbbra is releváns Java projektekhez, örökölt kódhoz és olyan forgatókönyvekhez, ahol a minimális konfiguráció fontos. A különbség nagy adatmennyiségek és összetett modellek esetén válik észrevehetővé.
A teljesítménytesztek azt mutatják, hogy a Moshi kódgenerálással 2-5-ször gyorsabban működik, mint a Gson a szerializációs és deszerializációs műveletekben. A Moshi legfontosabb előnye a Kotlin null-biztonságának helyes kezelése: ha egy mező hiányzik a JSON-ból, és a modellben non-null-ként van deklarálva alapértelmezett érték nélkül, a Moshi kivételt dob a deszerializációs fázisban, megelőzve a rejtett hibákat.
| Jellemző | Gson | Moshi |
|---|---|---|
| Mechanizmus | reflexió | kódgenerálás / reflexió |
| Null safety | nem veszi figyelembe | teljes Kotlin támogatás |
| Sebesség | közepes | magas |
| Alapértelmezett értékek | nem támogatja | támogatja |
| Kotlin Multiplatform | nem | igen |
| Könyvtár mérete | ~240 Kb | ~150 Kb |
A Moshi és Gson közötti választás a projekt kontextusától függ. Új Kotlin projektek profitálnak a Moshi-ból a típusbiztonság és teljesítmény révén. A Gson továbbra is ésszerű választás Java kód támogatásához, dinamikus JSON struktúrákhoz vagy amikor a csatlakozás egyszerűsége fontosabb, mint a sebesség. Kotlin Multiplatform esetében a Moshi az egyetlen a két változat közül, amely támogatja ezt a platformot.
A Gson-ról Moshi-ra való migráció során a fő változtatások az annotációkat és adaptereket érintik. A Gson @SerializedName-jét a @Json(name = "...") váltja fel, az egyedi JsonSerializer/JsonDeserializer-t pedig a @ToJson/@FromJson pár. Az alapértelmezett értékekkel és nullable mezőkkel rendelkező modellek esetén a Moshi kiszámíthatóbban viselkedik: ha egy non-null mező alapértelmezett érték nélkül hiányzik a JSON-ból, a Moshi JsonDataException-t dob, megelőzve a rejtett NPE-ket. A Retrofit integráció a MoshiConverterFactory segítségével egy függőséggel hozzáadható, és nem igényli a hálózati réteg architektúrájának módosítását. A ProGuard vagy R8 segítségével történő obfuszkációhoz meg kell adni a @JsonClass annotációval ellátott osztályok és a generált adapterek megőrzésére vonatkozó szabályokat, ellenkező esetben a szerializáció megsérül a release build-ben. Összességében a Gson-ról Moshi-ra való migráció indokolt új Kotlin projektekben, ahol a teljesítmény és a típusbiztonság fontos.
// Szerializáció összehasonlítása: Gson vs Moshi
data class Sample(
val name: String,
val count: Int,
val tags: List<String> = listOf()
)
// Gson: reflexióval működik
val gson = Gson()
val fromGson = gson.fromJson("""{"name":"test"}""",
Sample::class.java)
// count = 0 (default), de a null-biztonság nincs ellenőrizve
// Moshi: adaptert igényel, a null-biztonság explicit
@JsonClass(generateAdapter = true)
data class SampleMoshi(
val name: String,
val count: Int,
val tags: List<String> = listOf()
)
Gyakran Ismételt Kérdések
Moshi egy JSON könyvtár a Square-től Kotlin és Android számára, amely kódgenerálást használ reflexió helyett. Magas teljesítményt, a Kotlin null-biztonságának helyes kezelését és Kotlin Multiplatform kompatibilitást biztosít.
A Moshi felülmúlja a Gson-t sebességben (2-5-ször gyorsabb a kódgenerálásnak köszönhetően), biztonságban (figyelembe veszi a Kotlin null-annotációit) és méretben (~90 Kb-tal kisebb). Moshi támogatja továbbá a Kotlin Multiplatformot és az alapértelmezett értékeket a data class-okban.
A @JsonClass(generateAdapter = true) utasítja a Moshi-t, hogy generáljon adaptert ehhez az osztályhoz a fordítási fázisban. A generált adapter közvetlenül, reflexió nélkül végzi a szerializációt, ami maximális teljesítményt nyújt.
Hozzon létre egy osztályt @ToJson (szerializáció) és @FromJson (deszerializáció) annotációval ellátott metódusokkal. Regisztrálja a példányt a Moshi.Builder.add() segítségével. A Moshi automatikusan megtalálja és alkalmazza az adaptert a megfelelő típussal való munka során.
Igen, a Moshi támogatja a Kotlin Multiplatformot az 1.13.0 verziótól kezdődően. Ez teszi az egyetlen népszerű JSON megoldássá a KMP projektek számára, lehetővé téve a közös szerializációs kód használatát az összes célplatformon.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is