Το Moshi είναι μια σύγχρονη βιβλιοθήκη JSON από την Square, δημιουργημένη ειδικά για Kotlin και Android λαμβάνοντας υπόψη τους περιορισμούς του Gson. Είναι πλήρως συμβατή με το null-safety του Kotlin, παράγει κώδικα στο στάδιο μεταγλώττισης και δεν χρησιμοποιεί ανάκλαση, γεγονός που αυξάνει την απόδοση και την αξιοπιστία. Σύμφωνα με τα δεδομένα του Square Moshi, 2024, το Moshi παρέχει προβλέψιμη σειριοποίηση και υποστηρίζει προσαρμοσμένους προσαρμογείς για οποιουσδήποτε τύπους δεδομένων.
Κύρια σημεία
Moshi είναι μια βιβλιοθήκη JSON για JVM, Android και Kotlin Multiplatform, που δημιουργήθηκε από την Square (δημιουργούς των OkHttp και Retrofit). Σε αντίθεση με το Gson, το Moshi δεν βασίζεται στην ανάκλαση — οι προσαρμογείς παράγονται στο στάδιο μεταγλώττισης μέσω του σχολιασμού @JsonClass(generateAdapter = true). Αυτό καθιστά το Moshi ταχύτερο, ασφαλέστερο και πιο προβλέψιμο στην εργασία με κατασκευές ειδικές για Kotlin.
Η κύρια διαφορά του Moshi από τους προκατόχους του είναι η απόρριψη της ανάκλασης. Ανάκλαση επιτρέπει στο Gson να εργάζεται με οποιαδήποτε κλάση χωρίς προετοιμασία, αλλά το τίμημα είναι η αργή αρχικοποίηση, η αδυναμία βελτιστοποίησης από τον μεταγλωττιστή και ο κίνδυνος σφαλμάτων κατά τον χρόνο εκτέλεσης. Το Moshi απαιτεί ρητή υπόδειξη κλάσεων για παραγωγή κώδικα, αλλά ανταποδίδει με ταχύτητα χειρόγραφου κώδικα και πλήρη ασφάλεια τύπων στο στάδιο μεταγλώττισης.
// Σύνδεση Moshi στο 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"
}
// Απλό μοντέλο με παραγωγή κώδικα
@JsonClass(generateAdapter = true)
data class User(
@Json(name = "user_id")
val id: Int,
val name: String,
val email: String,
val avatar: String? = null
)
// Χρήση
val moshi = Moshi.Builder()
.build()
val jsonAdapter = moshi.adapter(User::class.java)
Για να ξεκινήσετε την εργασία με το Moshi, πρέπει να προστεθούν οι εξαρτήσεις στο build.gradle και να σχολιαστούν τα μοντέλα. Moshi.Builder χρησιμεύει ως σημείο εισόδου: μέσω αυτού προστίθενται ενσωματωμένοι προσαρμογείς για τυπικούς τύπους, προσαρμοσμένοι προσαρμογείς και διαμορφώνεται η συμπεριφορά της βιβλιοθήκης. Το Moshi υποστηρίζει προσαρμογείς για Date, Enum, Collection και Map αμέσως, αλλά για κλάσεις Kotlin απαιτείται η ενότητα moshi-kotlin. Σε αντίθεση με το Gson, το Moshi δεν χρησιμοποιεί ανάκλαση για κλάσεις Kotlin από προεπιλογή — γι' αυτό συνδέεται το KotlinJsonAdapterFactory, το οποίο χρησιμεύει ως εφεδρική επιλογή όταν δεν εφαρμόζεται παραγωγή κώδικα ή η κλάση δεν φέρει σχολιασμό @JsonClass. Αυτή η προσέγγιση εγγυάται ότι ο προγραμματιστής επιλέγει ρητά μεταξύ της απόδοσης της παραγωγής κώδικα και της ευελιξίας της ανάκλασης για κάθε συγκεκριμένη κλάση.
Μετά την κατασκευή του Moshi μέσω Builder, ο προγραμματιστής λαμβάνει μια παρουσία Moshi και ζητά έναν προσαρμογέα για την επιθυμητή κλάση. JsonAdapter είναι το κεντρικό αντικείμενο που εκτελεί σειριοποίηση μέσω toJson() και αποσειριοποίηση μέσω fromJson(). Το Moshi χρησιμοποιεί αυτόματα τον παραγόμενο προσαρμογέα εάν η κλάση φέρει σχολιασμό @JsonClass(generateAdapter = true), διαφορετικά εφαρμόζει τον ανακλαστικό KotlinJsonAdapterFactory ως εφεδρική επιλογή. Αυτή η προσέγγιση συνδυάζει την ταχύτητα της παραγωγής κώδικα με την ευελιξία του ανακλαστικού μηχανισμού για έργα οποιασδήποτε κλίμακας και επιπέδου πολυπλοκότητας. Το Moshi είναι κατάλληλο τόσο για μικρές εφαρμογές όσο και για μεγάλα εταιρικά έργα με εκατοντάδες μοντέλα δεδομένων.
// Διαμόρφωση Moshi με KotlinJsonAdapterFactory
val moshi = Moshi.Builder()
.add(KotlinJsonAdapterFactory())
.add(LocalDateAdapter())
.build()
// Χρήση προσαρμογέα
val adapter = moshi.adapter(User::class.java)
// Σειριοποίηση
val user = User(1, "Alice", "alice@test.com")
val json = adapter.toJson(user)
// Αποσειριοποίηση
val jsonString = """{"user_id":2,"name":"Bob","email":"bob@test.com"}"""
val parsedUser = adapter.fromJson(jsonString)
// Εργασία με λίστα
val listAdapter = moshi.adapter(
Types.newParameterizedType(
List::class.java,
User::class.java
)
)
Moshi χρησιμοποιεί σχολιασμούς για τη διαμόρφωση της σειριοποίησης και την υποστήριξη προσαρμοσμένων τύπων. Ο @Json(name = "...") ορίζει το κλειδί JSON για το πεδίο. Ο @Transient αποκλείει το πεδίο από τη σειριοποίηση. Ο @JsonClass(generateAdapter = true) ενεργοποιεί την παραγωγή κώδικα. Για προσαρμοσμένη λογική, το Moshi παρέχει τους σχολιασμούς @ToJson και @FromJson, οι οποίοι μπορούν να τοποθετηθούν σε ξεχωριστή κλάση προσαρμογέα.
Ο σχολιασμός @Json αντικαθιστά τον @SerializedName του Gson και λειτουργεί παρόμοια: το πεδίο kotlinName συνδέεται με το κλειδί JSON “kotlin_name”. Για τύπους που το Moshi δεν μπορεί να σειριοποιήσει από προεπιλογή (π.χ. LocalDate), ο προγραμματιστής δημιουργεί μια κλάση με μεθόδους @ToJson και @FromJson. Προσαρμογείς καταχωρούνται μέσω Moshi.Builder.add() και εφαρμόζονται καθολικά ή σε συγκεκριμένο τύπο. Το Moshi υποστηρίζει sealed class και πολυμορφική σειριοποίηση μέσω @JsonClass με ρητή υπόδειξη διακριτικού, επιτρέποντας την εργασία με ιεραρχίες τύπων σε JSON χωρίς χειροκίνητο έλεγχο πεδίων. Κατά την αποσειριοποίηση, το Moshi από προεπιλογή αγνοεί άγνωστα κλειδιά στο JSON, εξασφαλίζοντας συμβατότητα προς τα πίσω κατά την προσθήκη νέων πεδίων από την πλευρά του διακομιστή χωρίς τροποποίηση του κώδικα πελάτη. Για εντοπισμό σφαλμάτων, μπορεί να ενεργοποιηθεί η αυστηρή λειτουργία μέσω failOnUnknown, η οποία εκτοξεύει εξαίρεση κατά τον εντοπισμό άγνωστων κλειδιών.
// Προσαρμοσμένος προσαρμογέας για 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)
}
}
// Μοντέλο με σχολιασμούς 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
)
// Καταχώρηση προσαρμογέα
val moshi = Moshi.Builder()
.add(LocalDateAdapter())
.add(KotlinJsonAdapterFactory())
.build()
Η σύγκριση Moshi και Gson είναι συχνή ερώτηση κατά την επιλογή βιβλιοθήκης JSON για ένα έργο Android. Moshi κερδίζει στη σύγχρονη ανάπτυξη Kotlin χάρη στην παραγωγή κώδικα, το null-safety και την ταχύτητα. Το Gson παραμένει σχετικό για έργα Java, παλαιό κώδικα και σενάρια όπου η ελάχιστη διαμόρφωση είναι σημαντική. Η διαφορά γίνεται αισθητή σε μεγάλους όγκους δεδομένων και πολύπλοκα μοντέλα.
Οι δοκιμές απόδοσης δείχνουν ότι το Moshi με παραγωγή κώδικα λειτουργεί 2-5 φορές ταχύτερα από το Gson σε λειτουργίες σειριοποίησης και αποσειριοποίησης. Το βασικό πλεονέκτημα του Moshi είναι ο σωστός χειρισμός του null-safety του Kotlin: εάν ένα πεδίο απουσιάζει από το JSON και στο μοντέλο δηλώνεται ως non-null χωρίς προεπιλεγμένη τιμή, το Moshi εκτοξεύει εξαίρεση στο στάδιο αποσειριοποίησης, αποτρέποντας κρυφά σφάλματα.
| Χαρακτηριστικό | Gson | Moshi |
|---|---|---|
| Μηχανισμός | ανάκλαση | παραγωγή κώδικα / ανάκλαση |
| Null safety | δεν λαμβάνει υπόψη | πλήρης υποστήριξη Kotlin |
| Ταχύτητα | μέτρια | υψηλή |
| Προεπιλεγμένες τιμές | δεν υποστηρίζει | υποστηρίζει |
| Kotlin Multiplatform | όχι | ναι |
| Μέγεθος βιβλιοθήκης | ~240 Kb | ~150 Kb |
Η επιλογή μεταξύ Moshi και Gson εξαρτάται από το πλαίσιο του έργου. Νέα έργα σε Kotlin επωφελούνται από το Moshi χάρη στην ασφάλεια τύπων και την απόδοση. Το Gson παραμένει λογική επιλογή για υποστήριξη κώδικα Java, δυναμικών δομών JSON ή όταν η απλότητα σύνδεσης είναι σημαντικότερη από την ταχύτητα. Για Kotlin Multiplatform, το Moshi είναι η μοναδική από τις δύο παραλλαγές που υποστηρίζει αυτή την πλατφόρμα.
Κατά τη μετάβαση από Gson σε Moshi, οι κύριες αλλαγές αφορούν τους σχολιασμούς και τους προσαρμογείς. Ο @SerializedName του Gson αντικαθίσταται από @Json(name = "..."), και οι προσαρμοσμένοι JsonSerializer/JsonDeserializer — από το ζεύγος @ToJson/@FromJson. Για μοντέλα με προεπιλεγμένες τιμές και nullable πεδία, το Moshi συμπεριφέρεται πιο προβλέψιμα: εάν ένα non-null πεδίο χωρίς προεπιλεγμένη τιμή απουσιάζει από το JSON, το Moshi εκτοξεύει JsonDataException, αποτρέποντας κρυφά NPE. Η ενσωμάτωση με Retrofit μέσω MoshiConverterFactory προστίθεται με μία εξάρτηση και δεν απαιτεί αλλαγή της αρχιτεκτονικής του επιπέδου δικτύου. Για συσκότιση μέσω ProGuard ή R8 πρέπει να προστεθούν κανόνες διατήρησης κλάσεων με σχολιασμό @JsonClass και παραγόμενων προσαρμογέων, διαφορετικά η σειριοποίηση θα σπάσει στην τελική έκδοση. Συνολικά, η μετάβαση από Gson σε Moshi είναι δικαιολογημένη σε νέα έργα Kotlin όπου η απόδοση και η ασφάλεια τύπων είναι σημαντικές.
// Σύγκριση σειριοποίησης: Gson vs Moshi
data class Sample(
val name: String,
val count: Int,
val tags: List<String> = listOf()
)
// Gson: λειτουργεί μέσω ανάκλασης
val gson = Gson()
val fromGson = gson.fromJson("""{"name":"test"}""",
Sample::class.java)
// count = 0 (default), αλλά το null-safety δεν ελέγχεται
// Moshi: απαιτεί προσαρμογέα, το null-safety είναι ρητό
@JsonClass(generateAdapter = true)
data class SampleMoshi(
val name: String,
val count: Int,
val tags: List<String> = listOf()
)
Συχνές Ερωτήσεις
Moshi είναι μια βιβλιοθήκη JSON από την Square για Kotlin και Android που χρησιμοποιεί παραγωγή κώδικα αντί για ανάκλαση. Παρέχει υψηλή απόδοση, σωστό χειρισμό του null-safety του Kotlin και συμβατότητα με Kotlin Multiplatform.
Το Moshi υπερέχει του Gson σε ταχύτητα (2-5 φορές ταχύτερο χάρη στην παραγωγή κώδικα), ασφάλεια (λαμβάνει υπόψη τους null-σχολιασμούς Kotlin) και μέγεθος (~90 Kb μικρότερο). Moshi υποστηρίζει επίσης Kotlin Multiplatform και προεπιλεγμένες τιμές σε data class.
Ο @JsonClass(generateAdapter = true) δίνει εντολή στο Moshi να παράγει έναν προσαρμογέα για αυτή την κλάση στο στάδιο μεταγλώττισης. Ο παραγόμενος προσαρμογέας εκτελεί σειριοποίηση απευθείας, χωρίς ανάκλαση, προσφέροντας μέγιστη απόδοση.
Δημιουργήστε μια κλάση με μεθόδους σχολιασμένες με @ToJson (σειριοποίηση) και @FromJson (αποσειριοποίηση). Καταχωρήστε την παρουσία μέσω Moshi.Builder.add(). Το Moshi θα βρει και θα εφαρμόσει αυτόματα τον προσαρμογέα κατά την εργασία με τον αντίστοιχο τύπο.
Ναι, το Moshi υποστηρίζει Kotlin Multiplatform από την έκδοση 1.13.0. Αυτό το καθιστά τη μοναδική δημοφιλή λύση JSON για έργα KMP, επιτρέποντας τη χρήση κοινού κώδικα σειριοποίησης σε όλες τις πλατφόρμες-στόχους.
Σύνοψη
Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση
Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.
Διαβάστε επίσης