Gson — co to jest, biblioteka JSON dla Java i Kotlin

Autor: IT Sectr Opublikowano: 2026-03-15 Czas czytania: 8 min

Gson — biblioteka od Google do serializacji obiektów Java na JSON i odwrotnie, szeroko stosowana w programowaniu Android. Umożliwia konwersję złożonych grafów obiektów na zwarte ciągi JSON bez ręcznego pisania parserów. Według danych Google Gson, 2024, biblioteka ma ponad 23 tysiące gwiazdek na GitHub i pozostaje jednym z najpopularniejszych rozwiązań do pracy z JSON w ekosystemie Java i Kotlin.

Najważniejsze

  • Gson — biblioteka Google do serializacji JSON w Java i Kotlin
  • fromJson — deserializacja JSON do obiektu Java dowolnego typu
  • toJson — serializacja obiektu do ciągu JSON
  • @SerializedName — adnotacja do mapowania klucza JSON na pole klasy
  • TypeToken — praca z typami generycznymi i parametryzowanymi

Co to jest Gson

Gson — to biblioteka Java opracowana przez Google do konwersji obiektów na reprezentację JSON i odwrotnie. Wykorzystuje refleksję do analizy struktury klas, co umożliwia pracę bez wstępnej konfiguracji. Gson obsługuje dowolne obiekty Java, kolekcje, tablice, typy generyczne i klasy zagnieżdżone. Biblioteka nie wymaga adnotacji do podstawowego użycia, ale udostępnia je do precyzyjnego dostrajania. Główną wadą refleksji jest spadek wydajności podczas inicjalizacji i brak możliwości optymalizacji na etapie kompilacji, co jest szczególnie widoczne przy zimnym starcie aplikacji Android podczas deserializacji setek modeli. Mimo to Gson pozostaje niezawodnym wyborem dla większości projektów dzięki stabilności i obszernej dokumentacji.

Historia i miejsce w ekosystemie

Gson został wydany przez Google w 2008 roku i szybko stał się standardem de facto dla JSON w aplikacjach Android. Przed pojawieniem się Moshi i kotlinx.serialization Gson pozostawał jedynym popularnym wyborem dla projektów Kotlin. Prostota podłączenia — dodanie jednej zależności w build.gradle — i brak obowiązkowych adnotacji sprawiły, że Gson stał się popularny wśród programistów na każdym poziomie zaawansowania.

groovy
// Podłączenie Gson w build.gradle
dependencies {
    implementation 'com.google.code.gson:gson:2.10.1'
}

// Podstawowe użycie
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"}

Oprócz podstawowej serializacji, Gson udostępnia GsonBuilder do konfiguracji zachowania: formatowanie dat, wyłączanie escape'owania HTML, rejestr kluczy i niestandardowe instancje. GsonBuilder umożliwia również rejestrowanie niestandardowych JsonSerializer i JsonDeserializer dla typów, których biblioteka nie może przetworzyć automatycznie. Elastyczność konfiguracji czyni GsonBuilder niezbędnym i użytecznym narzędziem podczas dostosowywania biblioteki do specyficznych wymagań projektu w nowoczesnym programowaniu Android.

Podstawowe operacje toJson i fromJson

toJson przekształca obiekt Java w ciąg JSON, analizując jego pola poprzez refleksję. Domyślnie Gson uwzględnia wszystkie pola z wyjątkiem transient i static. Metoda obsługuje dowolne typy: prymitywy, obiekty, kolekcje i tablice. fromJson wykonuje odwrotną konwersję, przyjmując ciąg JSON i klasę docelowego obiektu, i zwraca instancję z wypełnionymi polami.

Konwersja obiektu na JSON

Podczas serializacji Gson rekurencyjnie przechodzi przez wszystkie pola obiektu, w tym zagnieżdżone. Odwołania cykliczne prowadzą do StackOverflowError, dlatego należy je wykluczyć za pomocą adnotacji @Expose lub niestandardowego adaptera. Dla kolekcji Gson zachowuje typ elementów, ale przy deserializacji listy z typami generycznymi wymagany jest TypeToken do zachowania informacji o typie.

kotlin
// data class z zagnieżdżonym obiektem
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"))

// Serializacja do JSON
val json = gson.toJson(employee)

// Deserializacja z JSON
val jsonString = """
{"id":2,"name":"Bob","address":{"city":"London","street":"Baker St"}}
"""
val parsed = gson.fromJson(jsonString, Employee::class.java)

Adnotacje i konfiguracja

Gson udostępnia zestaw adnotacji do zarządzania procesem serializacji. @SerializedName określa nazwę klucza JSON różniącą się od nazwy pola. @Expose zarządza uwzględnianiem pola w serializacji: Gson utworzony przez GsonBuilder.excludeFieldsWithoutExposeAnnotation() będzie przetwarzać tylko pola z @Expose. @Since i @Until kontrolują wersjonowanie pól.

@SerializedName i @Expose

Adnotacja @SerializedName rozwiązuje problem niezgodności nazw: serwer może używać snake_case, a w kodzie przyjęto camelCase. Adnotacja przyjmuje wartość i opcjonalne alternatywy dla wstecznej kompatybilności. @Expose pozwala ukryć wrażliwe pola (hasła, tokeny) przed serializacją, oznaczając je jako @Expose(serialize = false). Oprócz włączania i wyłączania, @Expose można łączyć z GsonBuilder.excludeFieldsWithoutExposeAnnotation w celu utworzenia białej listy pól, co pomaga kontrolować powierzchnię ataku podczas serializacji obiektów z dużą liczbą pól.

kotlin
// Model z adnotacjami 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 z filtrowaniem @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

Praca z typami generycznymi

Problem typów generycznych w Java i Kotlin polega na wymazywaniu typów podczas kompilacji. Gdy Gson deserializuje List<User>, nie zna typu elementu i zwraca List<Map<String, Any>>. Aby zachować informację o typie, Gson udostępnia TypeToken — abstrakcyjną klasę, która przechwytuje parametr typu przez anonimową klasę. Bez TypeToken programista musiałby ręcznie konwertować każdy element z Map na docelowy typ, co prowadzi do rozwlekłego kodu i utraty wydajności.

TypeToken dla list

TypeToken rozwiązuje problem wymazywania typów. Programista tworzy anonimowego potomka TypeToken z wymaganym parametrem typu, a Gson wykorzystuje informacje z sygnatury klasy do poprawnej deserializacji. TypeToken działa również z Map, Set i dowolnymi innymi typami parametryzowanymi, w tym zagnieżdżonymi typami generycznymi. W szczególności dla Map<String, List<User>> wymagany jest TypeToken z pełną sygnaturą zagnieżdżonego typu, w przeciwnym razie Gson deserializuje wartości jako List<Map<String, Any>> zamiast List<User>.

kotlin
// TypeToken do deserializacji listy
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)

// Niestandardowy deserializator
class LocalDateAdapter :
    JsonDeserializer<LocalDate> {

    override fun deserialize(
        json: JsonElement,
        typeOfT: java.lang.reflect.Type,
        context: JsonDeserializationContext
    ): LocalDate {
        return LocalDate.parse(json.asString)
    }
}

Do niestandardowej logiki serializacji Gson obsługuje interfejsy JsonSerializer i JsonDeserializer. Są one rejestrowane przez GsonBuilder.registerTypeAdapter() i umożliwiają przetwarzanie typów, których biblioteka nie może serializować automatycznie: dat Java 8, Enum z niestandardowymi wartościami lub klas zewnętrznych bez dostępu do kodu źródłowego. Podczas implementacji adaptera ważne jest monitorowanie wydajności: wywołanie refleksji wewnątrz niestandardowego adaptera niweczy zalety ręcznego zarządzania, dlatego zaleca się bezpośrednie wywołania metod i pól. W ekosystemie Gson istnieje również moduł gson-extras udostępniający adaptery dla popularnych typów, takich jak UUID, Optional i typy dat Joda-Time.

Konfiguracja przez GsonBuilder

GsonBuilder udostępnia dziesiątki metod do precyzyjnej konfiguracji serializacji. setPrettyPrinting dodaje wcięcia i znaki nowej linii w wyjściowym JSON dla czytelności. disableHtmlEscaping wyłącza escape'owanie znaków HTML w ciągach. setDateFormat ustawia format dat, co jest krytyczne przy pracy z serwerami używającymi niestandardowej reprezentacji czasu. setLenient włącza luźny tryb parsowania, który ignoruje niektóre błędy formatowania JSON. addDeserializationExclusionStrategy umożliwia programowe wykluczanie pól z deserializacji na podstawie niestandardowych strategii. Do debugowania przydatna jest metoda setPrettyPrinting w połączeniu z logowaniem — sprawia, że odpowiedzi JSON są czytelne w logach i ułatwia znajdowanie niezgodności.

Ważną możliwością GsonBuilder jest zarządzanie wersjonowaniem pól za pomocą adnotacji @Since i @Until. Programista określa wersję obiektu przez setVersion, a Gson automatycznie włącza lub wyklucza pola w zależności od ich adnotacji wersji. Jest to przydatne przy ewolucji API, gdy ten sam model jest używany dla różnych wersji protokołu serwerowego. GsonBuilder obsługuje również rejestrację TypeAdapterFactory do globalnego przetwarzania rodzin typów oraz complexMapKeySerialization do poprawnej pracy ze złożonymi kluczami Map.

Często zadawane pytania

Co to jest Gson w programowaniu Android?

Gson — to biblioteka Google do konwersji obiektów Java na JSON i odwrotnie. Jest szeroko stosowana w aplikacjach Android do parsowania odpowiedzi serwera, serializacji żądań i zapisywania danych w pamięci lokalnej.

Jak Gson obsługuje wartości null?

Domyślnie Gson pomija pola z null podczas serializacji. Aby włączyć wartości null, użyj GsonBuilder.serializeNulls(). Podczas deserializacji brakujące w JSON pola pozostają null lub przyjmują wartość domyślną dla typu.

Czym Gson różni się od Moshi?

Moshi nie używa refleksji dla klas Kotlin, co zapewnia wyższą wydajność i przewidywalne zachowanie. Moshi poprawnie obsługuje null-bezpieczeństwo Kotlin, podczas gdy Gson może deserializować null do pola non-null, powodując wyjątek.

Jak działa @SerializedName w Gson?

@SerializedName łączy klucz JSON z polem klasy, gdy ich nazwy się nie pokrywają. Na przykład dla pola kotlinName i klucza JSON „kotlin_name” adnotacja @SerializedName(„kotlin_name”) zapewnia poprawną konwersję.

Co to jest TypeToken w Gson?

TypeToken — to abstrakcyjna klasa, która przechwytuje parametr typu przez anonimową klasę. Jest niezbędna do deserializacji kolekcji i innych typów parametryzowanych, ponieważ z powodu wymazywania typów Gson nie może odtworzyć typu elementu w czasie wykonania.

Podsumowanie

  • Gson — biblioteka Google do serializacji JSON z obsługą Java i Kotlin
  • toJson i fromJson — podstawowe metody serializacji i deserializacji obiektów
  • @SerializedName — adnotacja do mapowania pól z kluczami JSON przy niezgodności nazw
  • @Expose — zarządzanie widocznością pól podczas serializacji przez GsonBuilder
  • TypeToken — rozwiązanie problemu wymazywania typów dla kolekcji parametryzowanych
  • GsonBuilder — konfiguracja formatowania, wersjonowania, dat i niestandardowych adapterów
  • JsonSerializer/JsonDeserializer — interfejsy do przetwarzania typów z niestandardową logiką

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również