Sparround

JSON serialization: Gson, Moshi, kotlinx.serialization

Üç əsas kitabxananın fərqi null-safety və Kotlin dəstəyindədir:

  • Gson — ən köhnə, reflection əsaslı. Kotlin-in null-safety-sindən xəbərsizdir: non-null String sahəsinə null yaza bilir → NPE sonra, gözlənilməz yerdə partlayır. Default dəyərlər reflection yolu ilə itir.
  • Moshi — Square-in müasir kitabxanası: codegen rejimində (@JsonClass(generateAdapter = true)) Kotlin null-safety-yə hörmət edir — null gələndə parse anında aydın exception. Reflection rejimi də var.
  • kotlinx.serialization — JetBrains-in compiler plugin həlli: @Serializable annotasiyası, reflection sıfır, multiplatform, default dəyərlər tam işləyir. Retrofit üçün rəsmi converter var.

Müsahibə sualının nüvəsi: "API null qaytarsa nə olur?" Gson — səssiz null non-null sahədə (gizli bomba); Moshi codegen / kotlinx — parse xətası dərhal (fail fast). Bank tətbiqində fail-fast üstündür: korrupt data ilə davam etməkdən yaxşıdır.

kotlin
// Gson — annotasiya yalnız ad uyğunluğu üçün
data class TxDto(
    @SerializedName("tx_id") val txId: String,      // Gson null yaza bilər!
    @SerializedName("amount") val amount: Long = 0  // default itir
)

// Moshi codegen — null gələrsə JsonDataException
@JsonClass(generateAdapter = true)
data class TxDto(
    @Json(name = "tx_id") val txId: String,
    @Json(name = "amount") val amount: Long = 0     // default işləyir
)

// kotlinx.serialization
@Serializable
data class TxDto(
    @SerialName("tx_id") val txId: String,
    @SerialName("amount") val amount: Long = 0      // default işləyir
)

Eyni DTO üç kitabxanada

Proguard/R8 tələsi: reflection əsaslı serialization (Gson, Moshi reflection) obfuscation-dan sonra sahə adlarını itirir — release build-də parse sınır, debug-da işləyir. Həll: DTO-lara @Keep/keep qaydaları, ya da codegen rejimlərinə keçid (onlara qayda lazım deyil). "Debug işləyir, release-də sınır" simptomunu eşidəndə ilk şübhələnəcəyin yer budur.

🛠 Tapşırıq

Null bombasını öz gözünlə gör: data class UserDto(val name: String) yaz və {"name": null} JSON-unu Gson ilə parse et.

  • Exception atılmadığını, sonra name.length çağırışında NPE gəldiyini təsdiqlə.
  • Eyni JSON-u Moshi codegen və ya kotlinx.serialization ilə parse et — xətanın harada çıxdığını müqayisə et.
  • Pul sahəsini Double kimi parse edib 0.1 + 0.2-ni çap et; sonra Long (qəpik) və BigDecimal variantını yaz.

Bitdi sayılır: "pulu niyə Double saxlamırıq" sualına konkret çıxışla cavab verirsənsə.

📚 Mənbələr və sənədlər