Skip to content

Moshi

Serialization & FormatsSerializationKotlin

What it is

Moshi is a JSON library for Kotlin and Java from Square, with a code-generating adapter option that respects Kotlin's null safety and default values.

Annotate classes @JsonClass(generateAdapter = true) for a generated adapter. Moshi enforces nullability and applies default values correctly.

Installation

implementation("com.squareup.moshi:moshi-kotlin:1.15.1")

Getting started

The smallest useful thing you can do with it, and what each part means.

Generated adapters and null safety
@JsonClass(generateAdapter = true)
data class Book(
    val id: Int,
    val title: String,                 // non-null is enforced
    @Json(name = "published_year") val year: Int,
    val tags: List<String> = emptyList(),
    val subtitle: String? = null,
)

val moshi = Moshi.Builder().build()
val adapter = moshi.adapter(Book::class.java)

val book = adapter.fromJson(json)   // throws if `title` is missing or null
val text = adapter.toJson(book)
That enforcement is the point. Gson would happily produce a Book whose non-null title is null, and the crash would surface much later somewhere unrelated.

Advanced usage

Where the library earns its place over a simpler alternative.

Polymorphism and custom adapters
val moshi = Moshi.Builder()
    .add(PolymorphicJsonAdapterFactory.of(Event::class.java, "type")
        .withSubtype(Click::class.java, "click")
        .withSubtype(KeyPress::class.java, "key")
        .withDefaultValue(UnknownEvent))   // tolerate new server types
    .add(InstantAdapter())
    .build()

class InstantAdapter {
    @ToJson fun toJson(value: Instant): String = value.toString()
    @FromJson fun fromJson(value: String): Instant = Instant.parse(value)
}
withDefaultValue matters for mobile clients: without it, a server adding a new event type crashes every app version already installed.

Errors and fixes

The failures you are most likely to hit, and what actually resolves them.

Required value 'title' missing at $
The JSON omits a non-null property. Give it a default, or make it nullable if the server genuinely may omit it.
Cannot serialize Kotlin type
The adapter was not generated. Add @JsonClass(generateAdapter = true) and the KSP dependency, or register KotlinJsonAdapterFactory.

Best practices

  • Use codegen (KSP) rather than reflection — it is faster and avoids shipping kotlin-reflect.
  • Set a default value on polymorphic adapters so unknown server types do not crash old clients.
  • Create one Moshi instance and reuse it; adapter lookup is cached on it.
  • Prefer kotlinx.serialization for Multiplatform; Moshi is JVM and Android only.

Background

Why it exists, and what it was reacting to.

Moshi was written after Gson, addressing its main Kotlin problem: Gson uses reflection to bypass constructors, so a non-null Kotlin property can end up holding null. Moshi's Kotlin support does not.