Moshi adalah pustaka JSON modern dari Square, dibuat khusus untuk Kotlin dan Android dengan mempertimbangkan keterbatasan Gson. Ini sepenuhnya kompatibel dengan null-safety Kotlin, menghasilkan kode pada tahap kompilasi dan tidak menggunakan refleksi, yang meningkatkan kinerja dan keandalan. Menurut data Square Moshi, 2024, Moshi menyediakan serialisasi yang dapat diprediksi dan mendukung adapter kustom untuk semua tipe data.
Poin Utama
Moshi adalah pustaka JSON untuk JVM, Android dan Kotlin Multiplatform, dibuat oleh Square (pembuat OkHttp dan Retrofit). Tidak seperti Gson, Moshi tidak bergantung pada refleksi — adapter dihasilkan pada tahap kompilasi melalui anotasi @JsonClass(generateAdapter = true). Ini membuat Moshi lebih cepat, lebih aman, dan lebih dapat diprediksi dalam bekerja dengan konstruksi khusus Kotlin.
Perbedaan utama Moshi dari pendahulunya adalah penolakan refleksi. Refleksi memungkinkan Gson bekerja dengan kelas apa pun tanpa persiapan, tetapi dengan harga inisialisasi lambat, ketidakmampuan optimasi oleh compiler, dan risiko kesalahan saat runtime. Moshi memerlukan penentuan kelas secara eksplisit untuk generasi kode, tetapi sebagai imbalannya memberikan kecepatan kode yang ditulis tangan dan keamanan tipe penuh pada tahap kompilasi.
// Menghubungkan Moshi di build.gradle
dependencies {
implementation "com.squareup.moshi:moshi:1.15.0"
implementation "com.squareup.moshi:moshi-kotlin:1.15.0"
kapt "com.squareup.moshi:moshi-kotlin-codegen:1.15.0"
}
// Model sederhana dengan generasi kode
@JsonClass(generateAdapter = true)
data class User(
@Json(name = "user_id")
val id: Int,
val name: String,
val email: String,
val avatar: String? = null
)
// Penggunaan
val moshi = Moshi.Builder()
.build()
val jsonAdapter = moshi.adapter(User::class.java)
Untuk mulai bekerja dengan Moshi, perlu menambahkan dependensi di build.gradle dan menganotasi model. Moshi.Builder berfungsi sebagai titik masuk: melaluinya ditambahkan adapter bawaan untuk tipe standar, adapter kustom, dan dikonfigurasi perilaku pustaka. Moshi mendukung adapter untuk Date, Enum, Collection dan Map secara bawaan, tetapi untuk kelas Kotlin diperlukan modul moshi-kotlin. Tidak seperti Gson, Moshi tidak menggunakan refleksi untuk kelas Kotlin secara default — untuk itu KotlinJsonAdapterFactory dihubungkan, yang berfungsi sebagai opsi cadangan ketika generasi kode tidak diterapkan atau kelas tidak dianotasi dengan @JsonClass. Pendekatan ini menjamin bahwa pengembang secara eksplisit memilih antara kinerja generasi kode dan fleksibilitas refleksi untuk setiap kelas tertentu.
Setelah membangun Moshi melalui Builder, pengembang mendapatkan instance Moshi dan meminta adapter untuk kelas yang diinginkan. JsonAdapter adalah objek sentral yang melakukan serialisasi melalui toJson() dan deserialisasi melalui fromJson(). Moshi secara otomatis menggunakan adapter yang dihasilkan jika kelas dianotasi dengan @JsonClass(generateAdapter = true), jika tidak, menerapkan KotlinJsonAdapterFactory reflektif sebagai opsi cadangan. Pendekatan ini menggabungkan kecepatan generasi kode dengan fleksibilitas mekanisme reflektif untuk proyek skala dan tingkat kompleksitas apa pun. Moshi sangat cocok untuk aplikasi kecil maupun proyek perusahaan besar dengan ratusan model data.
// Mengonfigurasi Moshi dengan KotlinJsonAdapterFactory
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.add(LocalDateAdapter())
.build()
// Penggunaan adapter
val adapter = moshi.adapter(User::class.java)
// Serialisasi
val user = User(1, "Alice", "alice@test.com")
val json = adapter.toJson(user)
// Deserialisasi
val jsonString = """{"user_id":2,"name":"Bob","email":"bob@test.com"}"""
val parsedUser = adapter.fromJson(jsonString)
// Bekerja dengan daftar
val listAdapter = moshi.adapter(
Types.newParameterizedType(
List::class.java,
User::class.java
)
)
Moshi menggunakan anotasi untuk mengonfigurasi serialisasi dan mendukung tipe kustom. @Json(name = "...") menetapkan kunci JSON untuk bidang. @Transient mengecualikan bidang dari serialisasi. @JsonClass(generateAdapter = true) mengaktifkan generasi kode. Untuk logika kustom, Moshi menyediakan anotasi @ToJson dan @FromJson, yang dapat ditempatkan di kelas adapter terpisah.
Anotasi @Json menggantikan @SerializedName milik Gson dan bekerja serupa: bidang kotlinName dihubungkan dengan kunci JSON “kotlin_name”. Untuk tipe yang tidak dapat diserialisasi Moshi secara default (misalnya LocalDate), pengembang membuat kelas dengan metode @ToJson dan @FromJson. Adapter didaftarkan melalui Moshi.Builder.add() dan diterapkan secara global atau untuk tipe tertentu. Moshi mendukung sealed class dan serialisasi polimorfik melalui @JsonClass dengan penunjuk diskriminator eksplisit, yang memungkinkan bekerja dengan hierarki tipe di JSON tanpa pemeriksaan bidang manual. Saat deserialisasi, Moshi secara default mengabaikan kunci yang tidak dikenal di JSON, yang memastikan kompatibilitas mundur saat menambahkan bidang baru di sisi server tanpa mengubah kode klien. Untuk debugging, mode ketat dapat diaktifkan melalui failOnUnknown, yang melempar pengecualian saat mendeteksi kunci yang tidak dikenal.
// Adapter kustom untuk LocalDate
class LocalDateAdapter {
@ToJson
fun toJson(date: LocalDate): String {
return date.format(DateTimeFormatter.ISO_LOCAL_DATE)
}
@FromJson
fun fromJson(dateString: String): LocalDate {
return LocalDate.parse(dateString)
}
}
// Model dengan anotasi Moshi
@JsonClass(generateAdapter = true)
data class Event(
@Json(name = "event_id")
val id: Int,
@Json(name = "event_date")
val date: LocalDate,
@Transient
val localCache: String? = null
)
// Pendaftaran adapter
val moshi = Moshi.Builder()
.add(LocalDateAdapter())
.add(KotlinJsonAdapterFactory())
.build()
Perbandingan Moshi dan Gson adalah pertanyaan umum saat memilih pustaka JSON untuk proyek Android. Moshi unggul dalam pengembangan Kotlin modern berkat generasi kode, null-safety, dan kecepatan. Gson tetap relevan untuk proyek Java, kode lawas, dan skenario di mana konfigurasi minimal penting. Perbedaan menjadi terlihat pada volume data besar dan model kompleks.
Uji kinerja menunjukkan bahwa Moshi dengan generasi kode bekerja 2-5 kali lebih cepat daripada Gson pada operasi serialisasi dan deserialisasi. Keunggulan utama Moshi adalah penanganan null-safety Kotlin yang benar: jika bidang tidak ada di JSON dan di model dinyatakan sebagai non-null tanpa nilai default, Moshi melempar pengecualian pada tahap deserialisasi, mencegah kesalahan tersembunyi.
| Karakteristik | Gson | Moshi |
|---|---|---|
| Mekanisme | refleksi | generasi kode / refleksi |
| Null safety | tidak memperhitungkan | dukungan penuh Kotlin |
| Kecepatan | sedang | tinggi |
| Nilai default | tidak mendukung | mendukung |
| Kotlin Multiplatform | tidak | ya |
| Ukuran pustaka | ~240 Kb | ~150 Kb |
Pilihan antara Moshi dan Gson tergantung pada konteks proyek. Proyek baru di Kotlin diuntungkan oleh Moshi berkat keamanan tipe dan kinerja. Gson tetap menjadi pilihan yang masuk akal untuk mendukung kode Java, struktur JSON dinamis, atau ketika kesederhanaan koneksi lebih penting daripada kecepatan. Untuk Kotlin Multiplatform, Moshi adalah satu-satunya dari dua varian yang mendukung platform ini.
Saat migrasi dari Gson ke Moshi, perubahan utama terkait anotasi dan adapter. @SerializedName milik Gson diganti dengan @Json(name = "..."), dan JsonSerializer/JsonDeserializer kustom — dengan pasangan @ToJson/@FromJson. Untuk model dengan nilai default dan bidang nullable, Moshi berperilaku lebih dapat diprediksi: jika bidang non-null tanpa nilai default tidak ada di JSON, Moshi melempar JsonDataException, mencegah NPE tersembunyi. Integrasi dengan Retrofit melalui MoshiConverterFactory ditambahkan dengan satu dependensi dan tidak memerlukan perubahan arsitektur lapisan jaringan. Untuk obfuskasi melalui ProGuard atau R8 perlu ditambahkan aturan pelestarian kelas yang dianotasi @JsonClass dan adapter yang dihasilkan, jika tidak serialisasi akan rusak di build rilis. Secara keseluruhan, migrasi dari Gson ke Moshi dibenarkan di proyek Kotlin baru di mana kinerja dan keamanan tipe penting.
// Perbandingan serialisasi: Gson vs Moshi
data class Sample(
val name: String,
val count: Int,
val tags: List<String> = listOf()
)
// Gson: bekerja melalui refleksi
val gson = Gson()
val fromGson = gson.fromJson("""{"name":"test"}""",
Sample::class.java)
// count = 0 (default), tetapi null-safety tidak diperiksa
// Moshi: memerlukan adapter, null-safety eksplisit
@JsonClass(generateAdapter = true)
data class SampleMoshi(
val name: String,
val count: Int,
val tags: List<String> = listOf()
)
Pertanyaan yang Sering Diajukan
Moshi adalah pustaka JSON dari Square untuk Kotlin dan Android yang menggunakan generasi kode alih-alih refleksi. Ini memberikan kinerja tinggi, penanganan null-safety Kotlin yang benar, dan kompatibilitas dengan Kotlin Multiplatform.
Moshi melampaui Gson dalam kecepatan (2-5 kali lebih cepat berkat generasi kode), keamanan (memperhitungkan anotasi null Kotlin) dan ukuran (~90 Kb lebih kecil). Moshi juga mendukung Kotlin Multiplatform dan nilai default di data class.
@JsonClass(generateAdapter = true) memerintahkan Moshi untuk menghasilkan adapter untuk kelas ini pada tahap kompilasi. Adapter yang dihasilkan melakukan serialisasi secara langsung, tanpa refleksi, yang memberikan kinerja maksimal.
Buat kelas dengan metode yang dianotasi dengan @ToJson (serialisasi) dan @FromJson (deserialisasi). Daftarkan instance melalui Moshi.Builder.add(). Moshi akan secara otomatis menemukan dan menerapkan adapter saat bekerja dengan tipe yang sesuai.
Ya, Moshi mendukung Kotlin Multiplatform mulai versi 1.13.0. Ini menjadikannya satu-satunya solusi JSON populer untuk proyek KMP, memungkinkan penggunaan kode serialisasi umum di semua platform target.
Kesimpulan
Kami akan mengembangkan aplikasi seluler turnkey
IT Sectr membuat aplikasi iOS dan Android untuk startup dan bisnis sejak 2017. Kami akan memberi saran dan mengusulkan solusi terbaik.
Baca juga