What it is
Kotlin's official serialisation library, generating encoders at compile time with a compiler plugin — no reflection, and Multiplatform-compatible.
Mark classes @Serializable and the plugin generates the serialiser. Json is configurable for lenient parsing, defaults and unknown keys.
Installation
plugins { kotlin("plugin.serialization") version "2.0.0" }Getting started
The smallest useful thing you can do with it, and what each part means.
@Serializable
data class Book(
val id: Int,
val title: String,
@SerialName("published_year") val year: Int,
val tags: List<String> = emptyList(),
val subtitle: String? = null,
)
val json = Json {
ignoreUnknownKeys = true // tolerate new fields from the server
encodeDefaults = false // omit values equal to their default
explicitNulls = false // omit nulls rather than writing null
}
val text = json.encodeToString(book)
val parsed = json.decodeFromString<Book>(text)Advanced usage
Where the library earns its place over a simpler alternative.
@Serializable
@JsonClassDiscriminator("type")
sealed class Event {
@Serializable @SerialName("click")
data class Click(val x: Int, val y: Int) : Event()
@Serializable @SerialName("key")
data class KeyPress(val key: String) : Event()
}
object InstantSerializer : KSerializer<Instant> {
override val descriptor = PrimitiveSerialDescriptor("Instant", PrimitiveKind.STRING)
override fun serialize(encoder: Encoder, value: Instant) =
encoder.encodeString(value.toString())
override fun deserialize(decoder: Decoder): Instant =
Instant.parse(decoder.decodeString())
}
@Serializable
data class Order(@Serializable(with = InstantSerializer::class) val placedAt: Instant)Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- Encountered an unknown key
- Set ignoreUnknownKeys = true, or add the field to the class.
- Serializer has not been found for type
- The class lacks @Serializable, or it is a third-party type needing a custom serialiser or @Contextual.
Best practices
- Set ignoreUnknownKeys = true for any API you do not control.
- Configure one Json instance and reuse it; constructing it per call is wasteful.
- Use @SerialName rather than renaming Kotlin properties to match the wire format.
- Prefer this over Jackson for Multiplatform and Android; Jackson remains fine on JVM-only servers.
Background
Why it exists, and what it was reacting to.
Jackson and Gson rely on reflection, which does not exist on Kotlin/Native and costs startup time on Android. kotlinx.serialization generates the code instead, and understands Kotlin's null safety and default values properly.
