Gson — کتابخانهای از گوگل برای سریالسازی اشیاء Java به JSON و بالعکس که به طور گسترده در توسعه Android استفاده میشود. این کتابخانه امکان تبدیل گرافهای پیچیده اشیاء به رشتههای JSON فشرده بدون نوشتن دستی تجزیهگرها را فراهم میکند. به گزارش Google Gson, 2024، این کتابخانه بیش از ۲۳ هزار ستاره در GitHub دارد و یکی از محبوبترین راهحلها برای کار با JSON در اکوسیستم Java و Kotlin باقی مانده است.
نکات اصلی
Gson — یک کتابخانه Java است که توسط گوگل برای تبدیل اشیاء به نمایش JSON و بالعکس توسعه یافته است. این کتابخانه از بازتاب (reflection) برای تحلیل ساختار کلاسها استفاده میکند که امکان کار بدون پیکربندی اولیه را فراهم میکند. Gson از اشیاء دلخواه Java، مجموعهها، آرایهها، ژنریکها و کلاسهای تو در تو پشتیبانی میکند. کتابخانه برای استفاده پایه نیازی به حاشیهنویسی ندارد، اما برای تنظیمات دقیق آنها را ارائه میدهد. عیب اصلی بازتاب — کاهش عملکرد در هنگام راهاندازی اولیه و عدم امکان بهینهسازی در مرحله کامپایل است که به ویژه در شروع سرد برنامه Android هنگام تبدیل صدها مدل قابل توجه است. با وجود این، Gson به دلیل پایداری و مستندات گسترده، انتخاب قابل اعتمادی برای اکثر پروژهها باقی میماند.
Gson توسط گوگل در سال ۲۰۰۸ منتشر شد و به سرعت به استاندارد دوفاکتو برای 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 را برای پیکربندی رفتار ارائه میدهد: قالببندی تاریخها، غیرفعال کردن escape-HTML، ثبت کلیدها و نمونههای سفارشی. 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<User> به عنوان List<Map<String, Any>> تبدیل میکند.
// 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 فرار از کاراکترهای HTML در رشتهها را غیرفعال میکند. setDateFormat قالب تاریخ را تعیین میکند که هنگام کار با سرورهایی که از نمایش غیراستاندارد زمان استفاده میکنند حیاتی است. setLenient حالت تجزیه سهلگیرانه را فعال میکند که برخی خطاهای قالببندی JSON را نادیده میگیرد. addDeserializationExclusionStrategy امکان حذف برنامهریزی شده فیلدها از تبدیل بر اساس استراتژیهای سفارشی را فراهم میکند. برای اشکالزدایی، متد setPrettyPrinting همراه با ثبت وقایع مفید است — پاسخهای JSON را در لاگها قابل خواندن میکند و یافتن ناسازگاریها را آسانتر میکند.
یک قابلیت مهم GsonBuilder مدیریت نسخهبندی فیلدها از طریق حاشیهنویسیهای @Since و @Until است. توسعهدهنده نسخه شیء را از طریق setVersion مشخص میکند و Gson به طور خودکار فیلدها را بر اساس حاشیهنویسی نسخه آنها شامل یا حذف میکند. این امر در تکامل API مفید است، زمانی که یک مدل برای نسخههای مختلف پروتکل سرور استفاده میشود. GsonBuilder همچنین از ثبت TypeAdapterFactory برای پردازش سراسری خانوادههای نوع و complexMapKeySerialization برای کار صحیح با کلیدهای Map پیچیده پشتیبانی میکند.
سوالات متداول
Gson — کتابخانه گوگل برای تبدیل اشیاء Java به JSON و بالعکس است. این کتابخانه به طور گسترده در برنامههای Android برای تجزیه پاسخهای سرور، سریالسازی درخواستها و ذخیره دادهها در حافظه محلی استفاده میشود.
به طور پیشفرض، Gson فیلدهای null را در هنگام سریالسازی نادیده میگیرد. برای فعالسازی مقادیر null از GsonBuilder.serializeNulls() استفاده کنید. در هنگام تبدیل معکوس، فیلدهای غایب در JSON null باقی میمانند یا مقدار پیشفرض نوع را میگیرند.
Moshi برای کلاسهای Kotlin از بازتاب استفاده نمیکند که عملکرد بالاتر و رفتار قابل پیشبینیتری ارائه میدهد. Moshi همچنین امنیت null کاتلین را به درستی مدیریت میکند، در حالی که Gson ممکن است null را به فیلد non-null تبدیل کرده و باعث ایجاد استثنا شود.
@SerializedName کلید JSON را به فیلد کلاس متصل میکند زمانی که نامها مطابقت ندارند. برای مثال، برای فیلد kotlinName و کلید JSON «kotlin_name»، حاشیهنویسی @SerializedName(«kotlin_name») تبدیل صحیح را تضمین میکند.
TypeToken — یک کلاس انتزاعی است که پارامتر نوع را از طریق یک کلاس ناشناس ضبط میکند. این کلاس برای تبدیل مجموعهها و سایر انواع پارامتری ضروری است، زیرا به دلیل پاک شدن انواع، Gson نمیتواند نوع عنصر را در زمان اجرا بازیابی کند.
خلاصه
ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد
IT Sectr از سال 2017 برنامههای iOS و Android را برای استارتاپها و کسبوکارها ایجاد میکند. ما به شما مشاوره میدهیم و بهترین راهحل را پیشنهاد خواهیم کرد.