Moshi: nyckelbegrepp, JSON Kotlin-bibliotek och hur det fungerar

Författare: IT Sectr Publicerad: 2026-03-15 Lästid: 8 min

Moshi är ett modernt JSON-bibliotek från Square, skapat speciellt för Kotlin och Android med hänsyn till Gsons begränsningar. Det är fullt kompatibelt med Kotlins null-säkerhet, genererar kod i kompileringsfasen och använder inte reflektion, vilket ökar prestanda och tillförlitlighet. Enligt uppgifter från Square Moshi, 2024, Moshi ger förutsägbar serialisering och stöder anpassade adaptrar för alla datatyper.

Huvudpunkter

  • Moshi — JSON-bibliotek från Square för Kotlin och Android utan reflektion
  • Kotlin-adapter — inbyggt stöd för data class, standardvärden och null safety
  • @Json — anteckning för att konfigurera fältnamn och ignorera egenskaper
  • Adaptrar — anpassad serialiseringslogik via @ToJson och @FromJson
  • Kodgenerering — Moshi genererar adaptrar i kompileringsfasen via kapt eller KSP

Vad är Moshi

Moshi är ett JSON-bibliotek för JVM, Android och Kotlin Multiplatform, skapat av Square (skaparna av OkHttp och Retrofit). Till skillnad från Gson förlitar sig Moshi inte på reflektion — adaptrar genereras i kompileringsfasen via anteckningen @JsonClass(generateAdapter = true). Detta gör Moshi snabbare, säkrare och mer förutsägbart vid arbete med Kotlin-specifika konstruktioner.

Filosofi och fördelar

Den huvudsakliga skillnaden mellan Moshi och dess föregångare är avståendet från reflektion. Reflektion tillåter Gson att arbeta med vilken klass som helst utan förberedelse, men till priset av långsam initiering, omöjlighet till optimering av kompilatorn och risk för fel under körning. Moshi kräver explicit angivelse av klasser för kodgenerering, men ger i gengäld hastigheten hos handskriven kod och fullständig typsäkerhet i kompileringsfasen.

kotlin
// Ansluta Moshi i 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"
}

// Enkel modell med kodgenerering
@JsonClass(generateAdapter = true)
data class User(
    @Json(name = "user_id")
    val id: Int,
    val name: String,
    val email: String,
    val avatar: String? = null
)

// Användning
val moshi = Moshi.Builder()
    .build()
val jsonAdapter = moshi.adapter(User::class.java)

Installation och konfiguration

För att börja arbeta med Moshi måste beroenden läggas till i build.gradle och modeller antecknas. Moshi.Builder fungerar som startpunkt: genom det läggs inbyggda adaptrar för standardtyper, anpassade adaptrar till och bibliotekets beteende konfigureras. Moshi stöder adaptrar för Date, Enum, Collection och Map direkt, men för Kotlin-klasser krävs modulen moshi-kotlin. Till skillnad från Gson använder Moshi som standard inte reflektion för Kotlin-klasser — för detta ansluts KotlinJsonAdapterFactory, som fungerar som reservalternativ när kodgenerering inte tillämpas eller klassen inte är antecknad med @JsonClass. Detta tillvägagångssätt garanterar att utvecklaren explicit väljer mellan prestandan hos kodgenerering och flexibiliteten hos reflektion för varje specifik klass.

Skapa Moshi och lägga till adaptrar

Efter att ha byggt Moshi via Builder får utvecklaren en Moshi-instans och begär en adapter för önskad klass. JsonAdapter är det centrala objektet som utför serialisering via toJson() och deserialisering via fromJson(). Moshi använder automatiskt den genererade adaptern om klassen är antecknad med @JsonClass(generateAdapter = true), annars tillämpar den reflektiva KotlinJsonAdapterFactory som reservalternativ. Denna metod kombinerar hastigheten hos kodgenerering med flexibiliteten hos den reflektiva mekanismen för projekt av alla storlekar och komplexitetsnivåer. Moshi passar både för små applikationer och stora företagsprojekt med hundratals datamodeller.

kotlin
// Konfigurera Moshi med KotlinJsonAdapterFactory
val moshi = Moshi.Builder()
    .add(KotlinJsonAdapterFactory())
    .add(LocalDateAdapter())
    .build()

// Använda adapter
val adapter = moshi.adapter(User::class.java)

// Serialisering
val user = User(1, "Alice", "alice@test.com")
val json = adapter.toJson(user)

// Deserialisering
val jsonString = """{"user_id":2,"name":"Bob","email":"bob@test.com"}"""
val parsedUser = adapter.fromJson(jsonString)

// Arbeta med lista
val listAdapter = moshi.adapter(
    Types.newParameterizedType(
        List::class.java,
        User::class.java
    )
)

Anteckningar och adaptrar

Moshi använder anteckningar för att konfigurera serialisering och stödja anpassade typer. @Json(name = "...") ställer in JSON-nyckeln för ett fält. @Transient utesluter ett fält från serialisering. @JsonClass(generateAdapter = true) aktiverar kodgenerering. För anpassad logik tillhandahåller Moshi anteckningarna @ToJson och @FromJson, som kan placeras i en separat adapterklass.

@Json och anpassade adaptrar

Anteckningen @Json ersätter Gsons @SerializedName och fungerar liknande: fältet kotlinName kopplas till JSON-nyckeln “kotlin_name”. För typer som Moshi inte kan serialisera som standard (t.ex. LocalDate) skapar utvecklaren en klass med metoder @ToJson och @FromJson. Adaptrar registreras via Moshi.Builder.add() och tillämpas globalt eller för en specifik typ. Moshi stöder sealed class och polymorf serialisering via @JsonClass med explicit angivelse av diskriminator, vilket möjliggör arbete med typhierarkier i JSON utan manuell fältkontroll. Vid deserialisering ignorerar Moshi som standard okända nycklar i JSON, vilket säkerställer bakåtkompatibilitet vid tillägg av nya fält på serversidan utan ändring av klientkoden. För felsökning kan strikt läge aktiveras via failOnUnknown, som kastar ett undantag vid upptäckt av okända nycklar.

kotlin
// Anpassad adapter för 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)
    }
}

// Modell med Moshi-anteckningar
@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
)

// Registrera adapter
val moshi = Moshi.Builder()
    .add(LocalDateAdapter())
    .add(KotlinJsonAdapterFactory())
    .build()

Moshi vs Gson

Jämförelse mellan Moshi och Gson är en vanlig fråga vid val av JSON-bibliotek för ett Android-projekt. Moshi vinner i modern Kotlin-utveckling tack vare kodgenerering, null-säkerhet och hastighet. Gson förblir relevant för Java-projekt, äldre kod och scenarier där minimal konfiguration är viktig. Skillnaden blir märkbar vid stora datamängder och komplexa modeller.

Prestanda och säkerhet

Prestandatester visar att Moshi med kodgenerering fungerar 2-5 gånger snabbare än Gson vid serialiserings- och deserialiseringsoperationer. Den viktigaste fördelen med Moshi är korrekt hantering av Kotlins null-säkerhet: om ett fält saknas i JSON och i modellen deklareras som non-null utan standardvärde, kastar Moshi ett undantag i deserialiseringsfasen, vilket förhindrar dolda fel.

EgenskapGsonMoshi
Mekanismreflektionkodgenerering / reflektion
Null safetytar inte hänsynfullt Kotlin-stöd
Hastighetmedelhög
Standardvärdenstöder intestöder
Kotlin Multiplatformnejja
Biblioteksstorlek~240 Kb~150 Kb

Valet mellan Moshi och Gson beror på projektets sammanhang. Nya projekt på Kotlin drar nytta av Moshi tack vare typsäkerhet och prestanda. Gson förblir ett rimligt val för stöd av Java-kod, dynamiska JSON-strukturer eller när anslutningsenkelhet är viktigare än hastighet. För Kotlin Multiplatform är Moshi den enda av de två varianterna som stöder denna plattform.

Vid migrering från Gson till Moshi rör de viktigaste ändringarna anteckningar och adaptrar. Gsons @SerializedName ersätts med @Json(name = "...") och anpassade JsonSerializer/JsonDeserializer — med paret @ToJson/@FromJson. För modeller med standardvärden och nullable fält beter sig Moshi mer förutsägbart: om ett non-null fält utan standardvärde saknas i JSON kastar Moshi JsonDataException, vilket förhindrar dolda NPE. Integration med Retrofit via MoshiConverterFactory läggs till med ett beroende och kräver ingen ändring av nätverkslagrets arkitektur. För obfuskering via ProGuard eller R8 måste regler läggas till för att bevara @JsonClass-antecknade klasser och genererade adaptrar, annars kommer serialiseringen att brytas i release-bygget. Sammantaget är migrering från Gson till Moshi motiverad i nya Kotlin-projekt där prestanda och typsäkerhet är viktiga.

kotlin
// Jämförelse av serialisering: Gson vs Moshi
data class Sample(
    val name: String,
    val count: Int,
    val tags: List<String> = listOf()
)

// Gson: fungerar via reflektion
val gson = Gson()
val fromGson = gson.fromJson("""{"name":"test"}""",
    Sample::class.java)
// count = 0 (default), men null-säkerhet kontrolleras inte

// Moshi: kräver adapter, null-säkerhet är explicit
@JsonClass(generateAdapter = true)
data class SampleMoshi(
    val name: String,
    val count: Int,
    val tags: List<String> = listOf()
)

Vanliga frågor

Vad är Moshi i Android?

Moshi är ett JSON-bibliotek från Square för Kotlin och Android som använder kodgenerering istället för reflektion. Det ger hög prestanda, korrekt hantering av Kotlins null-säkerhet och kompatibilitet med Kotlin Multiplatform.

Vad gör Moshi bättre än Gson?

Moshi överträffar Gson i hastighet (2-5 gånger snabbare tack vare kodgenerering), säkerhet (tar hänsyn till Kotlins null-anteckningar) och storlek (~90 Kb mindre). Moshi stöder även Kotlin Multiplatform och standardvärden i data class.

Hur fungerar anteckningen @JsonClass i Moshi?

@JsonClass(generateAdapter = true) instruerar Moshi att generera en adapter för denna klass i kompileringsfasen. Den genererade adaptern utför serialisering direkt, utan reflektion, vilket ger maximal prestanda.

Hur skapar jag en anpassad Moshi-adapter?

Skapa en klass med metoder antecknade med @ToJson (serialisering) och @FromJson (deserialisering). Registrera instansen via Moshi.Builder.add(). Moshi kommer automatiskt att hitta och tillämpa adaptern vid arbete med motsvarande typ.

Stöder Moshi Kotlin Multiplatform?

Ja, Moshi stöder Kotlin Multiplatform från version 1.13.0. Detta gör det till den enda populära JSON-lösningen för KMP-projekt, vilket möjliggör användning av gemensam serialiseringskod på alla målplattformar.

Sammanfattning

  • Moshi — modernt JSON-bibliotek från Square med kodgenerering istället för reflektion
  • @JsonClass — anteckning för adaptergenerering, ger hastigheten hos handskriven kod
  • @Json — konfiguration av JSON-nycklar, @Transient — uteslutning av fält från serialisering
  • @ToJson och @FromJson — enkelt API för anpassade adaptrar av alla typer
  • Null safety — Moshi tar hänsyn till Kotlin-anteckningar och kastar undantag vid mismatch
  • Prestanda — 2-5 gånger snabbare än Gson vid serialiserings- och deserialiseringsoperationer
  • Kotlin Multiplatform — KMP-stöd för universell serialiseringskod

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också