Data Models & Serialization
Shared models: write once, use everywhere
One of the biggest wins of KMP is defining your data models a single time in commonMain. The same User class is then used by your Android app, your iOS app, your networking and your database — no more keeping two copies in sync.
data class User(
val id: Int,
val name: String,
val email: String
)
kotlinx.serialization
To turn objects into JSON (and back) in a multiplatform way, Kotlin provides kotlinx.serialization. You annotate a class with @Serializable and the library handles the conversion on every platform.
import kotlinx.serialization.Serializable
@Serializable
data class User(
val id: Int,
val name: String,
val email: String
)
Encoding and decoding
import kotlinx.serialization.json.Json
val json = Json { ignoreUnknownKeys = true } // tolerate extra fields
// object -> JSON string
val text = json.encodeToString(User(1, "Anand", "a@x.com"))
// JSON string -> object
val user = json.decodeFromString<User>(text)
ignoreUnknownKeys = true is important in real apps: it stops decoding from crashing when the server sends extra fields you don’t use.
Handling API field names
When the JSON key differs from your Kotlin property, map it with @SerialName:
@Serializable
data class User(
val id: Int,
@SerialName("full_name") val name: String, // JSON key is full_name
val email: String? = null // optional / nullable
)
Nested and list models
@Serializable
data class ApiResponse(
val page: Int,
val users: List<User> // lists and nested objects just work
)
Why this matters for KMP
Because serialization runs in commonMain, both your Android and iOS apps parse JSON with the exact same code and the exact same rules. A change to a model updates everywhere at once — a major reduction in bugs.
Common mistakes
- Forgetting
@Serializable(you get a runtime/compile error). - Not setting
ignoreUnknownKeys, so the app crashes on extra server fields. - Forgetting to make genuinely optional fields nullable (
?) with a default.
Summary: Define models once in common code and annotate them@Serializable. Use kotlinx.serialization’sJsonto encode/decode on every platform, setignoreUnknownKeys, and map API names with@SerialName.