Moshi: Square's JSON Library for Kotlin and Java
A modern JSON library for Kotlin and Java.
At a glance
- What is it?
- Moshi is a JSON parsing and serialization library for Android, Kotlin, and Java from Square. It enforces a clear choice between compile-time code generation and runtime reflection for Kotlin classes, which shapes how you integrate it into a project.
- Who is it for?
- Moshi fits Android and JVM projects that want typed JSON adapters without a sprawling dependency chain. The code-generation path is the safer choice for Kotlin projects because it catches problems at compile time rather than at runtime.
- Can I use it commercially?
- Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 4 days ago.
- What is it written in?
- Mainly Kotlin, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What Moshi Solves and Who Uses It
JSON libraries for the JVM fall into two broad camps: those that rely entirely on runtime reflection and those that generate or register adapters explicitly. Moshi sits firmly in the second camp. It is aimed at Android and server-side JVM developers writing Kotlin or Java who want to convert JSON strings to typed model classes and back without writing manual parsing code.
The library ships from Square, the same team behind Retrofit and OkHttp. Its design assumes that adapters are registered or generated before a request is made, which keeps the runtime footprint small. The README states outright that plain Java-based reflection is unsupported on Kotlin classes, meaning any Kotlin project must choose one of the two supported paths before writing the first line of integration code.
The Adapter Model: How Moshi Converts JSON
The central object is `Moshi`, constructed via `Moshi.Builder`. From a `Moshi` instance you request a `JsonAdapter<T>` for a specific type, and that adapter handles both directions: `fromJson(json)` parses a string into an object, and `toJson(object)` serializes it back.
Built-in adapters cover Java's core types: primitives and their boxed counterparts, arrays, `Collection`, `List`, `Set`, `Map`, `String`, and enums. For model classes, Moshi maps JSON fields to object fields by name.
The Kotlin example from the README shows the full round-trip:
val moshi: Moshi = Moshi.Builder().build()
val jsonAdapter: JsonAdapter<BlackjackHand> = moshi.adapter<BlackjackHand>()
val blackjackHand = jsonAdapter.fromJson(json)
println(blackjackHand)And the reverse:
val json: String = jsonAdapter.toJson(blackjackHand)
println(json)This two-method API is the entirety of normal usage. The adapter holds all the logic, and the `Moshi` instance is stateless after construction.
Custom Type Adapters with @ToJson and @FromJson
When the default field-by-field encoding is too verbose or does not match the wire format, Moshi lets you replace it entirely. A type adapter is any class with methods annotated `@ToJson` and `@FromJson`. The README shows a `CardAdapter` that converts a `Card` object to a compact two-character string (for example, `"4H"` for the four of hearts or `"JD"` for the jack of diamonds) instead of the verbose `{"rank":"4","suit":"HEARTS"}` form:
class CardAdapter {
@ToJson fun toJson(card: Card): String {
return card.rank + card.suit.name.substring(0, 1)
}
@FromJson fun fromJson(card: String): Card {
if (card.length != 2) throw JsonDataException("Unknown card: $card")
val rank = card[0]
return when (card[1]) {
'C' -> Card(rank, Suit.CLUBS)
'D' -> Card(rank, Suit.DIAMONDS)
'H' -> Card(rank, Suit.HEARTS)
'S' -> Card(rank, Suit.SPADES)
else -> throw JsonDataException("unknown suit: $card")
}
}
}The adapter is registered at construction time:
val moshi = Moshi.Builder()
.add(CardAdapter())
.build()The `@FromJson` method is not limited to taking a `String` argument. It can accept any type that Moshi knows how to parse, and Moshi will first deserialize the JSON to that intermediate type before calling the method. This lets adapters compose without manual parsing.
The README also demonstrates combining two separate JSON fields (`begin_date` and `begin_time`) into a single field on a Kotlin data class by introducing an intermediate class that mirrors the wire format.
Kotlin Code Generation vs. Reflection
The most consequential decision when adding Moshi to a Kotlin project is which adapter strategy to use. The repository contains two Kotlin-specific modules: `moshi-kotlin/` for reflection-based adapters and `moshi-kotlin-codegen/` for compile-time code generation.
The README notes at the top that all Kotlin examples assume either `KotlinJsonAdapterFactory` (runtime reflection) or Kotlin code gen (annotation processing). Plain Java-based reflection on Kotlin classes is not supported.
Code generation produces `JsonAdapter` classes at compile time from annotated Kotlin classes, so problems surface before the app runs. Reflection defers that work to runtime and requires adding `KotlinJsonAdapterFactory` to the builder. The trade-off is build speed versus reliability: codegen adds an annotation processing step, reflection avoids it.
For projects already using annotation processing via kapt or KSP, codegen integrates naturally. For projects that want to avoid annotation processors, the reflection path works at the cost of a runtime dependency on Kotlin metadata.
Limitations and Cases Where Moshi Is the Wrong Tool
Moshi does not handle every JVM JSON use case well. The most important constraint is the Kotlin class restriction: if a codebase mixes Java and Kotlin model classes and expects Java-style reflection to work on both, Moshi will fail on the Kotlin side without the explicit adapter setup.
The library also has no built-in support for the full range of temporal types, polymorphic adapters from a JSON field, or schema validation. Projects that need any of those must write their own adapters or reach for a heavier library.
The repository has no GitHub releases listed, which makes version tracking dependent on the Maven artifact version rather than GitHub release notes.
For projects that need automatic polymorphic dispatch (where a `type` field in JSON determines which subclass to instantiate), Moshi requires either a third-party adapter library or custom adapter code. The README documents this pattern through the `moshi-adapters/` submodule listed in the repository, but the README itself does not walk through polymorphic adapter usage in detail.
Comparing Moshi to Gson
The most direct alternative is Gson, which is also a Google/Square-adjacent library for JVM JSON parsing. The key difference is in the Kotlin story: Gson works with Kotlin classes via Java reflection, which means it silently bypasses Kotlin's null safety. A `@NonNull` field in a Kotlin data class can receive a null from JSON with Gson and the compiler will not warn you.
Moshi's explicit adapter requirement for Kotlin classes is stricter but safer. When using codegen, a null arriving where none is expected throws a `JsonDataException` rather than silently passing a null into a non-nullable field.
Gson requires no setup for Kotlin classes; Moshi requires choosing and wiring an adapter approach. That difference matters most for teams adding Moshi to an existing codebase rather than starting from scratch.
Repository Layout and Maintenance
The repository is structured as a multi-module Gradle project. The top-level modules are `moshi/` (the core library), `moshi-kotlin/` (Kotlin reflection support), `moshi-kotlin-codegen/` (annotation-based code generation), `moshi-kotlin-tests/` (cross-module tests), `moshi-adapters/` (additional adapter implementations), and `examples/`. The build system uses `build.gradle.kts` and Kotlin DSL throughout.
The project is under the Apache-2.0 license, which permits use in proprietary applications without distributing source. The last push was on 2026-09-25, indicating the library receives regular maintenance. The repository has no GitHub releases; version tracking follows the Gradle artifact version in `gradle.properties`.
Editorial conclusion
Moshi fits Android and JVM projects that want typed JSON adapters without a sprawling dependency chain. The code-generation path is the safer choice for Kotlin projects because it catches problems at compile time rather than at runtime. Teams leaning on Java-based reflection for Kotlin classes will hit a hard wall, so verifying which codegen approach fits the build setup is the right first step. The Apache-2.0 license carries no practical restrictions for commercial use.
Frequently asked questions
How do I install Moshi in a Kotlin or Java project?
The README does not document dependency coordinates directly. The repository is a multi-module Gradle project with separate modules for the core library (moshi/), Kotlin reflection support (moshi-kotlin/), and compile-time code generation (moshi-kotlin-codegen/). You add whichever modules your project needs as build dependencies.
How do I use Moshi with Retrofit?
The README does not document Retrofit integration. It covers building a Moshi instance with Moshi.Builder() and obtaining a JsonAdapter<T> to call fromJson() and toJson(). Retrofit integration is handled through Retrofit's own converter API, which accepts a Moshi instance.
What is the difference between Moshi's Kotlin code generation and KotlinJsonAdapterFactory?
Code generation (moshi-kotlin-codegen/) uses annotation processing to produce JsonAdapter classes at compile time, catching mismatches before the app runs. KotlinJsonAdapterFactory (moshi-kotlin/) resolves adapters at runtime using reflection on Kotlin metadata. Both require explicit setup; plain Java-based reflection on Kotlin classes is not supported.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/square-moshi)