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.
kotlin
@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)Advanced usage
Where the library earns its place over a simpler alternative.
kotlin
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)
}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.
