CodeGym /Kurslar /JAVA 25 SELF /Gson — seriyalaşdırma və deserializasiya, konfiqurasiya

Gson — seriyalaşdırma və deserializasiya, konfiqurasiya

JAVA 25 SELF
Səviyyə, Dərs
Mövcuddur

1. Gson-a giriş

Artıq Jackson ilə tanış olmuşuq və niyə Java-da JSON ilə işləmək üçün de-fakto standart sayıldığını görmüşük. Amma başqa bir kitabxana da var ki, xüsusilə Android dünyasında böyük populyarlıq qazanıb — bu da Gson-dur. Gson Google-da Java obyektlərini JSON-a seriyalaşdırmaq və deserializasiya etmək üçün yüngül və sadə həll kimi yaradılıb. Onu aşağı giriş həddi üçün qiymətləndirirlər: başlamaq üçün demək olar ki, heç nəyi qurmağa ehtiyac yoxdur — tapşırıqların əksəriyyəti sözün əsl mənasında “qutudan çıxan kimi” həll olunur.

Gson-un başqa bir üstünlüyü onun yüngüllüyüdür. Kitabxana az yer tutur və çoxlu asılılıqları özü ilə gətirmir, buna görə də tətbiqin ölçüsünün kritik olduğu yerlərdə, məsələn, mobil cihazlarda tez-tez istifadə olunur. Gson Android layihələri üçün faktiki standart olub — kompaktlıq və sadəlik orada həlledici rol oynayır.

Yeri gəlmişkən, Gson adı Google JSON kimi açılır. Bəzən icmada zarafatcıl izahata da rast gəlinir — Genius’ Son (“dahinin oğlu”), amma bu, əlbəttə ki, rəsmi deyil. Sadəcə söz oyunudur.

Gson-u layihəyə qoşmaq

Əgər Maven və ya Gradle istifadə edirsinizsə, sadəcə asılılığı əlavə edin (versiya fərqli ola bilər):

Maven:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.10.1</version>
</dependency>

Gradle:

implementation 'com.google.code.gson:gson:2.10.1'

Biz hələ layihələrin yığılmasını öyrənməmişik, ona görə başlanğıc üçün jar faylını sadəcə Gson-un rəsmi səhifəsindən endirib layihəyə əlavə edə bilərsiniz.

2. Baza əməliyyatlar: seriyalaşdırma və deserializasiya

Gəlin Gson ilə obyektləri necə seriyalaşdırmaq və deserializasiya etmək olar, sadə bir sinif nümunəsində baxaq.

Nümunə: User sinfi

// Nümunələr üçün sinif
public class User {
    private String name;
    private int age;
    private boolean active;

    // Konstruktor
    public User(String name, int age, boolean active) {
        this.name = name;
        this.age = age;
        this.active = active;
    }

    // Getter və setterlər (Gson ehtiyac olduqda onlardan istifadə edir)
    public String getName() { return name; }
    public int getAge() { return age; }
    public boolean isActive() { return active; }
}

Seriyalaşdırma: obyekt → JSON

import com.google.gson.Gson;

public class GsonExample {
    public static void main(String[] args) {
        User user = new User("Alice", 25, true);

        Gson gson = new Gson();
        String json = gson.toJson(user);

        System.out.println(json);
        // {"name":"Alice","age":25,"active":true}
    }
}

Diqqət yetirin: sahələr sinifdəki adları ilə seriyalaşdırılır!

Deserializasiya: JSON → obyekt

public class GsonExample {
    public static void main(String[] args) {
        String json = "{\"name\":\"Bob\",\"age\":30,\"active\":false}";

        Gson gson = new Gson();
        User user = gson.fromJson(json, User.class);

        System.out.println(user.getName()); // Bob
        System.out.println(user.getAge());  // 30
        System.out.println(user.isActive());// false
    }
}

Obyekt siyahıları ilə iş

Gson kolleksiyalarla Jackson-a nisbətən bir az daha mürəkkəb işləyir, amma hər şey həll olunur.

import java.util.List;
import java.util.Arrays;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;

public class GsonListExample {
    public static void main(String[] args) {
        List<User> users = Arrays.asList(
            new User("Alice", 25, true),
            new User("Bob", 30, false)
        );

        Gson gson = new Gson();
        String json = gson.toJson(users);
        System.out.println(json);
        // [{"name":"Alice","age":25,"active":true},{"name":"Bob","age":30,"active":false}]

        // Siyahının deserializasiyası
        Type userListType = new TypeToken<List<User>>(){}.getType();
        List<User> users2 = gson.fromJson(json, userListType);
        System.out.println(users2.get(0).getName()); // Alice
    }
}

Vacib məqam: kolleksiyaları deserializasiya etmək üçün TypeToken<> istifadə edin!

3. Gson-un konfiqurasiyası: GsonBuilder

Gson çevik tənzimləməni GsonBuilder sinfi vasitəsilə təqdim edir. Onunla pretty printing-i aktivləşdirə, null seriyalaşdırılmasını, tarixlərin formatlanmasını və daha çoxunu qura bilərsiniz.

Nümunə: pretty printing və null-un seriyalaşdırılması

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class GsonBuilderExample {
    public static void main(String[] args) {
        User user = new User("Charlie", 0, false);

        Gson gson = new GsonBuilder()
            .setPrettyPrinting()        // Səliqəli çıxış (girintilər)
            .serializeNulls()           // null sahələri seriyalaşdırmaq
            .create();

        String json = gson.toJson(user);
        System.out.println(json);
        /*
        {
          "name": "Charlie",
          "age": 0,
          "active": false
        }
        */
    }
}

Tarixlərin formatlanması

Əgər sizdə Date tipli sahələr varsa, standartda Gson onları spesifik formatda seriyalaşdırır. Öz formatınızı təyin edə bilərsiniz:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.Date;

public class DateExample {
    private String event;
    private Date date;

    public DateExample(String event, Date date) {
        this.event = event;
        this.date = date;
    }
}

public class Main {
    public static void main(String[] args) {
        DateExample meeting = new DateExample("Team Meeting", new Date());

        Gson gson = new GsonBuilder()
            .setDateFormat("yyyy-MM-dd HH:mm:ss")
            .create();

        String json = gson.toJson(meeting);
        System.out.println(json);
        // {"event":"Team Meeting","date":"2024-06-10 13:45:23"}
    }
}

4. Gson annotasiyaları: seriyalaşdırmaya nəzarət

Gson seriyalaşdırma və deserializasiyaya daha dəqiq nəzarət üçün annotasiyaları dəstəkləyir.

@SerializedName — sahənin adını dəyişmək

Əgər JSON-da sahənin başqa adla adlandırılmasını istəyirsinizsə, @SerializedName istifadə edin:

import com.google.gson.annotations.SerializedName;

public class User {
    @SerializedName("full_name")
    private String name;
    private int age;
    private boolean active;

    public User(String name, int age, boolean active) {
        this.name = name;
        this.age = age;
        this.active = active;
    }
}

İndi seriyalaşdırma zamanı sahənin adı full_name olacaq:

User user = new User("Diana", 28, true);
String json = new Gson().toJson(user);
// {"full_name":"Diana","age":28,"active":true}

@Expose — yalnız işarələnmiş sahələrin seriyalaşdırılması

Yalnız müəyyən sahələri seriyalaşdırmaq istəyirsinizsə, @Expose istifadə edin və Gson-u uyğun qurun:

import com.google.gson.annotations.Expose;

public class User {
    @Expose
    private String name;

    @Expose
    private int age;

    private boolean active; // seriyalaşdırılmır

    public User(String name, int age, boolean active) {
        this.name = name;
        this.age = age;
        this.active = active;
    }
}

@Expose dəstəyi ilə Gson yaradırıq:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

Gson gson = new GsonBuilder()
    .excludeFieldsWithoutExposeAnnotation()
    .create();

User user = new User("Eve", 21, false);
String json = gson.toJson(user);
// {"name":"Eve","age":21}

@Since/@Until — versiyaya görə şərti seriyalaşdırma
@Since və @Until-dən yalnız müəyyən versiyalar üçün sahələrin seriyalaşdırılması məqsədilə istifadə etmək olar (praktikada nadir hallarda tətbiq olunur, amma bilmək faydalıdır).

5. Gson-un xüsusiyyətləri və məhdudiyyətləri

Daxili obyektlərlə iş

Gson daxili obyektlərlə əla işləyir:

public class Profile {
    private User user;
    private String bio;

    public Profile(User user, String bio) {
        this.user = user;
        this.bio = bio;
    }
}

Profile profile = new Profile(new User("Frank", 27, true), "Java developer");
String json = new Gson().toJson(profile);
// {"user":{"name":"Frank","age":27,"active":true},"bio":"Java developer"}

Kolleksiyalarla iş

Kolleksiyaların (List, Map) seriyalaşdırılmasında problem yoxdur, amma deserializasiya üçün TypeToken istifadə edin (yuxarıya baxın).

Gson-un Jackson-la müqayisədə məhdudiyyətləri

  • Java record sinifləri üçün dəstək yoxdur (son versiyalara qədər)
  • Yeni tarix/zaman API-larına məhdud dəstək (məsələn, LocalDate, LocalDateTime — xüsusi adapterlər lazımdır)
  • Jackson annotasiyaları ilə işləyə bilmir
  • Mürəkkəb polimorf strukturlar üçün “qutudan çıxan kimi” dəstək yoxdur
  • İkitərəfli istinadlar (döngüsellik) üçün avtomatik dəstək yoxdur

Fərdi (custom) adapterlər (TypeAdapter)

Standart imkanlar kifayət etmirsə, mürəkkəb tiplərin seriyalaşdırılması/deserializasiyası üçün öz adapterinizi yaza bilərsiniz.

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;

public class BooleanAsIntAdapter extends TypeAdapter<Boolean> {
    @Override
    public void write(JsonWriter out, Boolean value) throws IOException {
        out.value(value ? 1 : 0);
    }

    @Override
    public Boolean read(JsonReader in) throws IOException {
        return in.nextInt() == 1;
    }
}

// İstifadə:
Gson gson = new GsonBuilder()
    .registerTypeAdapter(Boolean.class, new BooleanAsIntAdapter())
    .create();

6. Təcrübə: parametrlərlə seriyalaşdırma və deserializasiya

Gəlin tədris tətbiqinizi inkişaf etdirək və istifadəçilər siyahısının JSON formatında saxlanmasını və yüklənməsini əlavə edək.

Annotasiyalı User sinfi

import com.google.gson.annotations.SerializedName;
import com.google.gson.annotations.Expose;

public class User {
    @Expose
    @SerializedName("full_name")
    private String name;

    @Expose
    private int age;

    private boolean active; // seriyalaşdırılmır

    public User(String name, int age, boolean active) {
        this.name = name;
        this.age = age;
        this.active = active;
    }

    // getterlər, setterlər...
}

İstifadəçilər siyahısını JSON-a saxlayırıq

import java.util.List;
import java.util.Arrays;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

public class SaveUsers {
    public static void main(String[] args) {
        List<User> users = Arrays.asList(
            new User("Ivan", 23, true),
            new User("Olga", 19, false)
        );

        Gson gson = new GsonBuilder()
            .excludeFieldsWithoutExposeAnnotation()
            .setPrettyPrinting()
            .create();

        String json = gson.toJson(users);
        System.out.println(json);
        /*
        [
          {
            "full_name": "Ivan",
            "age": 23
          },
          {
            "full_name": "Olga",
            "age": 19
          }
        ]
        */
    }
}

İstifadəçilər siyahısını JSON-dan yükləyirik

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
import java.util.List;

public class LoadUsers {
    public static void main(String[] args) {
        String json = "[{\"full_name\":\"Ivan\",\"age\":23},{\"full_name\":\"Olga\",\"age\":19}]";

        Gson gson = new GsonBuilder()
            .excludeFieldsWithoutExposeAnnotation()
            .create();

        Type userListType = new TypeToken<List<User>>(){}.getType();
        List<User> users = gson.fromJson(json, userListType);

        for (User user : users) {
            System.out.println(user.getName() + " (" + user.getAge() + ")");
        }
        // Ivan (23)
        // Olga (19)
    }
}

7. Gson və Jackson-un müqayisəsi

Xüsusiyyət Gson Jackson
İstifadə rahatlığı +++++ (çox sadə) +++ (bir az daha çətindir)
Kitabxananın ölçüsü Kiçik Daha böyük
Sürət Sürətli, amma bir az yavaşdır Çox sürətli
Çeviklik Orta Yüksək (daha çox tənzimləmə)
Annotasiyalara dəstək Öz annotasiyaları (@SerializedName) Öz annotasiyaları (@JsonProperty və s.)
Yeni tiplərə dəstək Məhduddur Möhtəşəm (Java 8+, record)
Android dəstəyi Möhtəşəm Yaxşı, amma daha ağırdır
Tarixlərlə iş Yalnız adapterlərlə Qutudan çıxan kimi
Polimorfizm Məhduddur Çevik şəkildə tənzimlənir

8. Gson ilə işləyərkən tipik səhvlər

Səhv №1: Kolleksiyalar üçün TypeToken istifadə etmirsiniz.
Əgər siyahı və ya xəritəni deserializasiya edirsinizsə, mütləq TypeToken<> istifadə edin, əks halda qəribə xətalar və ya boş kolleksiyalar əldə edəcəksiniz.

Səhv №2: Parametrsiz konstruktor yoxdur.
Gson susmaya görə konstruktor olmadan da işləyə bilər, amma bəzən mürəkkəb obyektlərin deserializasiyasında belə konstruktor olmadıqda xətalar yarana bilər. Deserializasiya planlayırsınızsa, həmişə parametrsiz konstruktor əlavə etmək daha yaxşıdır.

Səhv №3: Sahə adlarının uyğun gəlməməsi.
Əgər JSON-da sahənin adı "full_name", sinifdə isə — "name"dirsə, @SerializedName("full_name") annotasiyası olmadan sahə bağlanmayacaq və dəyər null olacaq.

Səhv №4: Private sahələrlə problemlər.
Gson private sahələri seriyalaşdıra bilir, amma yalnız private sahələr və heç bir getter/setter yoxdursa, bəzən deserializasiya zamanı problemlər yaranır. Getter və setterlərdən istifadə etmək daha yaxşıdır.

Səhv №5: Tarixlərlə iş.
Susmaya görə Gson Date-i əlverişsiz formatda seriyalaşdırır. LocalDate, LocalDateTime və digər yeni tiplər üçün xüsusi adapterlər olmadan seriyalaşdırma xətaları olacaq.

Səhv №6: @Expose istifadə etmirsiniz, amma excludeFieldsWithoutExposeAnnotation() aktivdir.
Əgər siz excludeFieldsWithoutExposeAnnotation()-u aktiv etmisinizsə, amma sahələri @Expose annotasiyası ilə işarələməmisinizsə, onlar nə seriyalaşdırılacaq, nə də deserializasiya olunacaq — nəticə boş JSON və ya sahələri null olan obyektlər olacaq.

1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
Tələbə məlumatlarının xarici sistemlə sinxronizasiyası 🎓
Tələbə məlumatlarının xarici sistemlə sinxronizasiyası 🎓
1
Tapşırıq
JAVA 25 SELF, səviyyə, dərs
Bağlanıb
İctimai profillərin sosial şəbəkədə yaradılması 🌐
İctimai profillərin sosial şəbəkədə yaradılması 🌐
Şərhlər
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION