Gson — a Google könyvtára Java objektumok JSON-ba és vissza történő szerializálására, széles körben használt Android fejlesztésben. Lehetővé teszi összetett objektumgráfok tömör JSON karakterláncokká alakítását kézi elemzők írása nélkül. A Google Gson, 2024 adatai szerint a könyvtár több mint 23 ezer csillaggal rendelkezik a GitHub-on, és továbbra is az egyik legnépszerűbb megoldás a JSON-nal való munkához a Java és Kotlin ökoszisztémában.
Főbb pontok
A Gson — egy Java könyvtár, amelyet a Google fejlesztett objektumok JSON megjelenítéssé és vissza történő konvertálására. Reflektációt használ az osztályok szerkezetének elemzéséhez, ami lehetővé teszi a munkát előzetes konfiguráció nélkül. A Gson tetszőleges Java objektumokat, gyűjteményeket, tömböket, generikusokat és beágyazott osztályokat támogat. A könyvtár nem igényel annotációkat az alapvető használathoz, de finomhangoláshoz biztosítja azokat. A reflektáció fő hátránya a teljesítmény csökkenése inicializáláskor és az optimalizálás lehetetlensége a fordítási szakaszban, ami különösen észrevehető az Android alkalmazás hidegindításakor több száz modell deszerializálásakor. Ennek ellenére a Gson megbízható választás marad a legtöbb projekt számára a stabilitásnak és a kiterjedt dokumentációnak köszönhetően.
A Gson-t a Google 2008-ban adta ki, és gyorsan a JSON de facto szabványává vált az Android alkalmazásokban. A Moshi és a kotlinx.serialization megjelenése előtt a Gson maradt az egyetlen népszerű választás a Kotlin projektek számára. Az egyszerű csatlakoztatás — egy függőség hozzáadása a build.gradle-ben — és a kötelező annotációk hiánya népszerűvé tette a Gson-t minden szintű fejlesztő körében.
// Gson hozzáadása a build.gradle-ben
dependencies {
implementation 'com.google.code.gson:gson:2.10.1'
}
// Alapvető használat
data class User(
val id: Int,
val name: String,
val email: String
)
val gson = Gson()
val user = User(1, "John", "john@test.com")
val json = gson.toJson(user)
println(json) // {"id":1,"name":"John","email":"john@test.com"}
Az alap szerializáción kívül a Gson GsonBuilder-t biztosít a viselkedés konfigurálásához: dátumok formázása, HTML escape kikapcsolása, kulcsregiszter és egyedi példányok. A GsonBuilder lehetővé teszi egyedi JsonSerializer és JsonDeserializer regisztrálását is olyan típusokhoz, amelyeket a könyvtár nem tud automatikusan feldolgozni. A konfiguráció rugalmassága nélkülözhetetlen és hasznos eszközzé teszi a GsonBuilder-t a könyvtár projekt specifikus követelményeihez való igazításában a modern Android fejlesztésben.
A toJson egy Java objektumot JSON karakterlánccá alakít, a mezőit reflektáción keresztül elemezve. Alapértelmezés szerint a Gson az összes mezőt tartalmazza, kivéve a transient és static mezőket. A metódus minden típust támogat: primitíveket, objektumokat, gyűjteményeket és tömböket. A fromJson fordított átalakítást végez, fogad egy JSON karakterláncot és a célobjektum osztályát, és visszaad egy példányt kitöltött mezőkkel.
A szerializáció során a Gson rekurzívan bejárja az objektum összes mezőjét, beleértve a beágyazottakat is. A ciklikus hivatkozások StackOverflowError-hoz vezetnek, ezért azokat ki kell zárni a @Expose annotációval vagy egy egyedi adapterrel. Gyűjtemények esetén a Gson megőrzi az elemek típusát, de a lista generikusokkal történő deszerializálásakor TypeToken szükséges a típusinformáció megőrzéséhez.
// data class beágyazott objektummal
data class Address(
val city: String,
val street: String
)
data class Employee(
val id: Int,
val name: String,
val address: Address
)
val gson = Gson()
val employee = Employee(1, "Alice",
Address("New York", "5th Ave"))
// Szerializálás JSON-ba
val json = gson.toJson(employee)
// Deszerializálás JSON-ból
val jsonString = """
{"id":2,"name":"Bob","address":{"city":"London","street":"Baker St"}}
"""
val parsed = gson.fromJson(jsonString, Employee::class.java)
A Gson annotációkészletet biztosít a szerializációs folyamat kezeléséhez. A @SerializedName megadja a JSON kulcs nevét, amely eltér a mező nevétől. A @Expose kezeli a mező szerializációba való bevonását: a GsonBuilder.excludeFieldsWithoutExposeAnnotation() segítségével létrehozott Gson csak a @Expose annotációval rendelkező mezőket dolgozza fel. A @Since és @Until a mezők verziókezelését szabályozza.
A @SerializedName annotáció megoldja a név-eltérések problémáját: a szerver snake_case-t használhat, míg a kódban a camelCase az elfogadott. Az annotáció értéket és opcionális alternatívákat fogad a visszamenőleges kompatibilitás érdekében. A @Expose lehetővé teszi az érzékeny mezők (jelszavak, tokenek) elrejtését a szerializáció elől azáltal, hogy @Expose(serialize = false) jelöléssel látja el őket. A bevonáson és kizáráson kívül a @Expose kombinálható a GsonBuilder.excludeFieldsWithoutExposeAnnotation-nel a mezők fehér listájának létrehozásához, ami segít a támadási felület szabályozásában a sok mezővel rendelkező objektumok szerializálásakor.
// Modell Gson annotációkkal
data class UserResponse(
@SerializedName("user_id")
val userId: Int,
@SerializedName("full_name",
alternate = [Alternative("name")])
val fullName: String,
@Expose(serialize = false)
val password: String
)
// Gson @Expose szűréssel
val gson = GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.setPrettyPrinting()
.create()
val user = UserResponse(1, "John", "secret123")
println(gson.toJson(user))
// {"user_id":1,"full_name":"John"} — password excluded
A generikusok problémája Java-ban és Kotlin-ban a típusok fordítás közbeni törlésében rejlik. Amikor a Gson deszerializál egy List<User>-t, nem ismeri az elem típusát, és List<Map<String, Any>>-t ad vissza. A típusinformáció megőrzéséhez a Gson TypeToken-t biztosít — egy absztrakt osztályt, amely egy anonim osztályon keresztül rögzíti a típusparamétert. TypeToken nélkül a fejlesztőnek manuálisan kellene konvertálnia minden elemet Map-ből a cél típusba, ami terjedelmes kódhoz és teljesítményvesztéshez vezet.
A TypeToken megoldja a típusok törlésének problémáját. A fejlesztő létrehoz egy anonim TypeToken leszármazottat a kívánt típusparaméterrel, és a Gson az osztály aláírásából származó információt használja a helyes deszerializáláshoz. A TypeToken működik Map, Set és bármely más paraméterezett típussal, beleértve a beágyazott generikusokat is. Különösen a Map<String, List<User>> esetében szükség van egy TypeToken-ra a beágyazott típus teljes aláírásával, különben a Gson az értékeket List<User> helyett List<Map<String, Any>>-ként deszerializálja.
// TypeToken lista deszerializálásához
data class Product(
val id: Int,
val title: String,
val price: Double
)
val jsonArray = """
[
{"id":1,"title":"Phone","price":599.0},
{"id":2,"title":"Laptop","price":1299.0}
]
"""
val gson = Gson()
val listType = object : TypeToken<List<Product>>() {}
val products: List<Product> =
gson.fromJson(jsonArray, listType.type)
// Egyedi deszerializátor
class LocalDateAdapter :
JsonDeserializer<LocalDate> {
override fun deserialize(
json: JsonElement,
typeOfT: java.lang.reflect.Type,
context: JsonDeserializationContext
): LocalDate {
return LocalDate.parse(json.asString)
}
}
Az egyedi szerializációs logikához a Gson támogatja a JsonSerializer és JsonDeserializer interfészeket. Ezek a GsonBuilder.registerTypeAdapter() segítségével regisztrálhatók, és lehetővé teszik olyan típusok feldolgozását, amelyeket a könyvtár nem tud automatikusan szerializálni: Java 8 dátumok, nem szabványos értékekkel rendelkező Enum-ok vagy harmadik féltől származó osztályok forráskódhoz való hozzáférés nélkül. Az adapter implementálásakor fontos a teljesítmény figyelése: a reflektáció meghívása az egyedi adapteren belül semmissé teszi a kézi kezelés előnyeit, ezért előnyben részesítjük a metódusok és mezők közvetlen meghívását. A Gson ökoszisztémában létezik a gson-extras modul is, amely adaptereket biztosít gyakori típusokhoz, mint az UUID, Optional és a Joda-Time dátum típusok.
A GsonBuilder több tucat metódust biztosít a szerializáció finomhangolásához. A setPrettyPrinting behúzásokat és új sorokat ad a kimeneti JSON-hoz az olvashatóság érdekében. A disableHtmlEscaping kikapcsolja a HTML karakterek escape-elését a karakterláncokban. A setDateFormat beállítja a dátumformátumot, ami kritikus a nem szabványos időmegjelenítést használó szerverekkel való munka során. A setLenient bekapcsolja a megengedő elemzési módot, amely figyelmen kívül hagy néhány JSON formázási hibát. Az addDeserializationExclusionStrategy lehetővé teszi mezők programozott kizárását a deszerializációból egyedi stratégiák alapján. Hibakereséshez a setPrettyPrinting metódus hasznos a naplózással kombinálva — olvashatóvá teszi a JSON válaszokat a naplókban, és leegyszerűsíti az eltérések keresését.
A GsonBuilder fontos képessége a mezők verziókezelésének irányítása a @Since és @Until annotációkon keresztül. A fejlesztő a setVersion segítségével adja meg az objektum verzióját, és a Gson automatikusan beveszi vagy kizárja a mezőket a verziójuk annotációjától függően. Ez hasznos az API evolúciója során, amikor ugyanaz a modell a szerverprotokoll különböző verzióihoz használatos. A GsonBuilder támogatja továbbá a TypeAdapterFactory regisztrálását a típuscsaládok globális feldolgozásához és a complexMapKeySerialization-t az összetett Map kulcsokkal való helyes munkához.
Gyakran Ismételt Kérdések
A Gson — egy Google könyvtár Java objektumok JSON-ba és vissza történő konvertálására. Széles körben használják Android alkalmazásokban a szerverválaszok elemzésére, kérések szerializálására és adatok helyi tárolóban történő mentésére.
Alapértelmezés szerint a Gson kihagyja a null mezőket a szerializáció során. A null értékek engedélyezéséhez használja a GsonBuilder.serializeNulls() metódust. A deszerializáció során a JSON-ból hiányzó mezők nullok maradnak, vagy a típus alapértelmezett értékét veszik fel.
A Moshi nem használ reflektációt a Kotlin osztályokhoz, ami magasabb teljesítményt és kiszámítható viselkedést biztosít. A Moshi helyesen kezeli a Kotlin null-biztonságát is, míg a Gson deszerializálhat null-t egy non-null mezőbe, kivételt okozva.
A @SerializedName összeköti a JSON kulcsot az osztály mezőjével, amikor a nevük nem egyezik. Például a kotlinName mező és a „kotlin_name” JSON kulcs esetén a @SerializedName(„kotlin_name”) annotáció biztosítja a helyes konvertálást.
A TypeToken — egy absztrakt osztály, amely egy anonim osztályon keresztül rögzíti a típusparamétert. Szükséges a gyűjtemények és más paraméterezett típusok deszerializálásához, mivel a típusok törlése miatt a Gson nem tudja visszaállítani az elem típusát futásidőben.
Ö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