kotlinx.serialization: a compiler plugin for Kotlin data classes, not a reflection library
Kotlin multiplatform / multi-format serialization
At a glance
- What is it?
- kotlinx.serialization generates serializers at compile time for @Serializable classes across JVM, JS and Native, with JSON, Protobuf, CBOR, Hocon and Properties formats. It is the right default inside Kotlin, and the wrong one when your classes are not Kotlin or your JSON shape is unknown at build time.
- Who is it for?
- Adopt it if your model classes are Kotlin and you compile with the serialization plugin, especially on multiplatform targets where reflection-based libraries are weak. Do not adopt it if your classes are Java or come from a framework you cannot annotate, or if you need an XML format, since the README lists JSON, Protobuf, CBOR, Hocon and Properties and no XML module.
- 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 received new commits within the last day.
- 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 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem kotlinx.serialization solves for Kotlin codebases
Reflection-based serializers look at your classes at runtime. On the JVM that works, but it costs startup time, it can break under R8 shrinking, and on Kotlin/JS and Kotlin/Native the reflection machinery is limited or absent. kotlinx.serialization takes the opposite route: the README describes the project as a "compiler plugin, that generates visitor code for serializable classes", paired with a runtime library and format modules. The serializer for a class is ordinary generated code, so it survives shrinking and works on every Kotlin target the project supports: JVM, JS and Native.
The intended user is a Kotlin developer who owns the data classes being written to the wire. Marking a class with @Serializable is a compile-time contract. If the class is not Kotlin, or you cannot add the annotation because it lives in a library you do not control, the plugin has nothing to generate and the model does not fit. That boundary is the whole design, not an accident of the API.
How the compiler plugin and format modules fit together
There are three moving parts. The Gradle plugin runs during compilation and produces serializer implementations for every @Serializable class and for the standard collections. The core artifact, kotlinx-serialization-core, holds the serialization API itself but, as the README puts it, "does not have a bundled serialization format with it". Formats are separate modules: kotlinx-serialization-json, plus Protobuf, CBOR, Hocon and Properties.
That split is why the plugin version and the library version do not move together. The README states that new versions of the serialization plugin are released in tandem with each new Kotlin compiler version, while the runtime library has "different coordinates, repository and versioning". In practice you pin two numbers: the Kotlin version used for both the language plugin and the serialization plugin, and the library version from Maven Central. The README example uses Kotlin 2.3.20 for the plugins and 1.12.0 for kotlinx-serialization-json. Mixing them by habit is the most common setup error.
The data flow is direct. A format object such as Json walks the generated serializer for your class, and the serializer reads and writes fields through the format's encoder and decoder. Because the serializer is generated rather than discovered, the format sees a fixed structure at compile time.
Installing kotlinx.serialization with Gradle and encoding a first object
The README gives two required steps: add the serialization plugin, then add the library dependency. The Kotlin DSL block below applies the serialization plugin alongside the JVM plugin at the same version, which is the version pairing the README uses in its example.
plugins {
kotlin("jvm") version "2.3.20"
kotlin("plugin.serialization") version "2.3.20"
}Then declare the runtime dependency from Maven Central. Use the JSON artifact for JSON; the core artifact alone gives you the API without a format.
repositories {
mavenCentral()
}
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.12.0")
}With both in place, annotate a data class and call the format. This is the README's own example, and running it prints the JSON object followed by the reconstructed instance.
import kotlinx.serialization.*
import kotlinx.serialization.json.*
@Serializable
data class Project(val name: String, val language: String)
fun main() {
val data = Project("kotlinx.serialization", "Kotlin")
val string = Json.encodeToString(data)
println(string) // {"name":"kotlinx.serialization","language":"Kotlin"}
val obj = Json.decodeFromString<Project>(string)
println(obj) // Project(name=kotlinx.serialization, language=Kotlin)
}If the compiler reports an unresolved serializer for a type, the plugin is usually missing or is applied at a different Kotlin version than the language plugin. The README also notes that Kotlin versions before 1.4.0 are not supported by the stable release, so very old toolchains are out of scope.
Where the plugin model breaks down
The compiler plugin is also the main limitation. A type you cannot annotate cannot be serialized by the generated path, so wrapping a third-party Java model, a dynamic map with an unknown schema, or a class generated after compilation pushes you back toward a reflection-based library. The plugin only sees what the compiler sees.
Android has a second sharp edge. The README states that ProGuard rules ship with the library and keep serializers for all serializable classes retained after shrinking, so no extra setup is needed. It then carves out an exception: those rules "do not affect serializable classes if they have named companion objects". If your serializable class has a named companion object, you must edit proguard-rules.pro yourself, and the README notes that the required R8 rules differ depending on the compatibility mode. That is a real failure mode with a runtime symptom, not a compile error.
Format coverage is another boundary. The README lists JSON, Protobuf, CBOR, Hocon and Properties. XML is not among them, so a project that needs XML has to look elsewhere or convert between representations.
kotlinx.serialization compared with Jackson, Gson and Moshi
Jackson, Gson and Moshi all read your classes at runtime. Jackson and Gson are JVM libraries built around reflection and Java type erasure; Moshi adds code generation on Android but still targets Java and Kotlin classes through adapters you register. None of them is a Kotlin compiler plugin, and none of them covers Kotlin/Native or Kotlin/JS the way this project does.
The practical difference shows up in three places. First, the model: with kotlinx.serialization the annotation is part of compilation, so an unannotated class is a compile-time problem rather than a runtime surprise. Second, defaults and nullability: Kotlin's type system is what the generated serializer encodes, so a non-null String field stays non-null. Third, shrinking: generated serializers are reachable code, which is why the Android story is mostly handled by the bundled rules. The trade-off is reach. A Java class from a shared library, or a payload whose shape is only known at runtime, fits a reflection-based library better than it fits this one.
Maintenance, versions and the Apache-2.0 licence
The repository is not archived, and the last push was on 2026-09-21. Releases are frequent: v1.12.0-RC on 2026-09-04, v1.11.0 on 2026-04-09 and v1.10.0 on 2026-01-21. The README ties plugin releases to Kotlin compiler releases, so upgrading Kotlin generally means upgrading the serialization plugin in the same commit. Budget for that: a Kotlin upgrade is a serialization upgrade, and the two version numbers in your build file move together.
The library is licensed under Apache-2.0, and the repository carries a license/ directory alongside LICENSE.txt. Apache-2.0 is a permissive licence with an explicit patent grant and a notice requirement; if you redistribute the artifacts, keep the notices intact. That is a description of the licence text, not legal advice for your product.
Editorial conclusion
Adopt it if your model classes are Kotlin and you compile with the serialization plugin, especially on multiplatform targets where reflection-based libraries are weak. Do not adopt it if your classes are Java or come from a framework you cannot annotate, or if you need an XML format, since the README lists JSON, Protobuf, CBOR, Hocon and Properties and no XML module. Before committing, verify that the plugin version matches your Kotlin compiler version and that your R8 or ProGuard rules cover any serializable class with a named companion object, because the bundled rules do not.
Frequently asked questions
What is kotlinx.serialization?
It is a Kotlin multiplatform serialization library made of a compiler plugin that generates visitor code for serializable classes, a runtime core API, and format modules. It supports classes marked @Serializable and the standard collections.
How do I add kotlinx.serialization to a Gradle project?
Add the kotlin("plugin.serialization") plugin at the same version as your Kotlin plugin, then add a dependency on org.jetbrains.kotlinx:kotlinx-serialization-json from mavenCentral. The plugin version follows the Kotlin compiler version, while the library version is separate.
How do I serialize JSON in Kotlin with kotlinx.serialization?
Annotate a data class with @Serializable, then call Json.encodeToString on an instance and Json.decodeFromString to read it back. The README's example prints {"name":"kotlinx.serialization","language":"Kotlin"} and reconstructs the object.
How can I convert a JSON string to a data class in Kotlin?
Use Json.decodeFromString with the target type as the type argument, for example Json.decodeFromString<Project>(string), after marking the data class @Serializable. The compiler plugin generates the serializer the decoder needs.
How do I use kotlinx.serialization with Retrofit?
The README does not document Retrofit integration, so it says nothing about which converter to register or how to configure it. It covers the Gradle plugin setup and the JSON artifact dependency only.
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/kotlin-kotlinx-serialization)