Gson — библиотека компаније Google за серијализацију Java објеката у JSON и назад, широко коришћена у Android развоју. Омогућава претварање сложених графова објеката у компактне JSON низове без ручног писања парсера. Према подацима Google Gson, 2024, библиотека има преко 23 хиљаде звездица на GitHub-у и остаје једно од најпопуларнијих решења за рад са JSON-ом у екосистему Java и Kotlin.
Главне тачке
Gson — је Java библиотека коју је развио Google за претварање објеката у JSON приказ и назад. Користи рефлексију за анализу структуре класа, што омогућава рад без претходне конфигурације. Gson подржава произвољне Java објекте, колекције, низове, генерике и угнежђене класе. Библиотека не захтева анотације за основну употребу, али их пружа за фино подешавање. Главни недостатак рефлексије је смањење перформанси при иницијализацији и немогућност оптимизације у фази компилације, што је посебно приметно при хладном старту Android апликације при десеријализацији стотина модела. Упркос томе, Gson остаје поуздан избор за већину пројеката захваљујући стабилности и опсежној документацији.
Gson је објавио Google 2008. године и брзо је постао де факто стандард за JSON у Android апликацијама. Пре појаве Moshi и kotlinx.serialization, Gson је остао једини популарни избор за Kotlin пројекте. Једноставност повезивања — додавање једне зависности у build.gradle — и одсуство обавезних анотација учинили су Gson популарним међу програмерима свих нивоа.
// Додавање Gson-а у build.gradle
dependencies {
implementation 'com.google.code.gson:gson:2.10.1'
}
// Основна употреба
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"}
Поред основне серијализације, Gson пружа GsonBuilder за подешавање понашања: форматирање датума, искључивање HTML escape-а, регистар кључева и прилагођене инстанце. GsonBuilder такође омогућава регистрацију прилагођених JsonSerializer и JsonDeserializer за типове које библиотека не може аутоматски обрадити. Флексибилност конфигурације чини GsonBuilder незаменљивим и корисним алатом при прилагођавању библиотеке специфичним захтевима пројекта у модерном Android развоју.
toJson претвара Java објекат у JSON низ, анализирајући његова поља кроз рефлексију. Подразумевано, Gson укључује сва поља осим transient и static. Метод подржава све типове: примитиве, објекте, колекције и низове. fromJson врши обрнуту конверзију, примајући JSON низ и класу циљног објекта, и враћа инстанцу са попуњеним пољима.
Приликом серијализације, Gson рекурзивно обилази сва поља објекта, укључујући угнежђена. Цикличне референце доводе до StackOverflowError-а, па их треба искључити путем @Expose анотације или прилагођеног адаптера. За колекције, Gson чува тип елемената, али при десеријализацији листе са генерицима потребан је TypeToken за чување информације о типу.
// data class са угнежђеним објектом
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"))
// Серијализација у JSON
val json = gson.toJson(employee)
// Десеријализација из JSON-а
val jsonString = """
{"id":2,"name":"Bob","address":{"city":"London","street":"Baker St"}}
"""
val parsed = gson.fromJson(jsonString, Employee::class.java)
Gson пружа сет анотација за управљање процесом серијализације. @SerializedName одређује име JSON кључа које се разликује од имена поља. @Expose управља укључивањем поља у серијализацију: Gson креиран кроз GsonBuilder.excludeFieldsWithoutExposeAnnotation() обрађиваће само поља са @Expose. @Since и @Until контролишу верзионисање поља.
Анотација @SerializedName решава проблем неусаглашености имена: сервер може користити snake_case, а у коду је усвојен camelCase. Анотација прихвата вредност и опционе алтернативе за уназадну компатибилност. @Expose омогућава скривање осетљивих поља (лозинке, токени) од серијализације, означавајући их као @Expose(serialize = false). Поред укључивања и искључивања, @Expose се може комбиновати са GsonBuilder.excludeFieldsWithoutExposeAnnotation за креирање беле листе поља, што помаже у контроли површине напада при серијализацији објеката са великим бројем поља.
// Модел са Gson анотацијама
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 филтрирањем
val gson = GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.setPrettyPrinting()
.create()
val user = UserResponse(1, "John", "secret123")
println(gson.toJson(user))
// {"user_id":1,"full_name":"John"} — password excluded
Проблем генерика у Java и Kotlin-у лежи у брисању типова током компилације. Када Gson десеријализује List<User>, он не зна тип елемента и враћа List<Map<String, Any>>. Да би се сачувала информација о типу, Gson пружа TypeToken — апстрактну класу која хвата параметар типа кроз анонимну класу. Без TypeToken-а, програмер би морао ручно да претвара сваки елемент из Map-е у циљни тип, што доводи до гломазног кода и губитка перформанси.
TypeToken решава проблем брисања типова. Програмер креира анонимног наследника TypeToken-а са потребним параметром типа, а Gson користи информацију из потписа класе за исправну десеријализацију. TypeToken такође ради са Map, Set и било којим другим параметризованим типовима, укључујући угнежђене генерике. Посебно, за Map<String, List<User>> потребан је TypeToken са комплетним потписом угнежђеног типа, иначе Gson десеријализује вредности као List<Map<String, Any>> уместо List<User>.
// TypeToken за десеријализацију листе
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)
// Прилагођени десеријализатор
class LocalDateAdapter :
JsonDeserializer<LocalDate> {
override fun deserialize(
json: JsonElement,
typeOfT: java.lang.reflect.Type,
context: JsonDeserializationContext
): LocalDate {
return LocalDate.parse(json.asString)
}
}
За прилагођену логику серијализације, Gson подржава интерфејсе JsonSerializer и JsonDeserializer. Они се региструју кроз GsonBuilder.registerTypeAdapter() и омогућавају обраду типова које библиотека не може аутоматски серијализовати: Java 8 датуми, Enum са нестандардним вредностима или класе трећих страна без приступа изворном коду. Приликом имплементације адаптера, важно је пратити перформансе: позив рефлексије унутар прилагођеног адаптера поништава предности ручног управљања, па се преферирају директни позиви метода и поља. У Gson екосистему постоји и модул gson-extras који пружа адаптере за уобичајене типове попут UUID, Optional и Joda-Time типова датума.
GsonBuilder пружа десетине метода за фино подешавање серијализације. setPrettyPrinting додаје увлачења и нове редове у излазни JSON за читљивост. disableHtmlEscaping искључује escape-овање HTML знакова у низовима. setDateFormat поставља формат датума, што је критично при раду са серверима који користе нестандардне приказе времена. setLenient укључује опуштени режим парсирања који игнорише неке грешке форматирања JSON-а. addDeserializationExclusionStrategy омогућава програмско искључивање поља из десеријализације на основу прилагођених стратегија. За отклањање грешака, метода setPrettyPrinting је корисна у комбинацији са логирањем — чини JSON одговоре читљивим у логовима и олакшава проналажење неусаглашености.
Важна могућност GsonBuilder-а је управљање верзионисањем поља кроз анотације @Since и @Until. Програмер одређује верзију објекта путем setVersion, а Gson аутоматски укључује или искључује поља у зависности од њихове верзионе анотације. Ово је корисно при еволуцији API-ја, када се исти модел користи за различите верзије серверског протокола. GsonBuilder такође подржава регистрацију TypeAdapterFactory за глобалну обраду фамилија типова и complexMapKeySerialization за исправан рад са сложеним Map кључевима.
Често постављана питања
Gson — је Google библиотека за претварање Java објеката у JSON и назад. Широко се користи у Android апликацијама за парсирање одговора сервера, серијализацију захтева и чување података у локалном складишту.
Подразумевано, Gson прескаче поља са null при серијализацији. За укључивање null вредности користите GsonBuilder.serializeNulls(). При десеријализацији, поља која недостају у JSON-у остају null или узимају подразумевану вредност за тип.
Moshi не користи рефлексију за Kotlin класе, што пружа веће перформансе и предвидљиво понашање. Moshi такође исправно обрађује null-безбедност Kotlin-а, док Gson може десеријализовати null у non-null поље, изазивајући изузетак.
@SerializedName повезује JSON кључ са пољем класе када се њихова имена не поклапају. На пример, за поље kotlinName и JSON кључ „kotlin_name”, анотација @SerializedName(„kotlin_name”) обезбеђује исправну конверзију.
TypeToken — је апстрактна класа која хвата параметар типа кроз анонимну класу. Потребна је за десеријализацију колекција и других параметризованих типова, јер због брисања типова Gson не може да поврати тип елемента током извршавања.
Резиме
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође