Kotlin Serialization Shenanigans
/ 2 min read
Table of Contents
It’s been a while since I did some serialization implementation on Android. I forgot how painful this was to implement. This is for my future self, in case I reencounter this stupid shenanigans again.
Gradle Imports
First, import Retrofit, Kotlinx Serialization and Jake Wharton’s Retrofit Kotlinx Serialization Converter.
implementation("com.squareup.retrofit2:retrofit:2.9.0")implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.3")implementation("com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0")On the build.gradle project level file, don’t forget to also add the dependency inside the plugin section.
plugins { id("org.jetbrains.kotlin.plugin.serialization") version "1.9.22" apply false}Back to your app level build.gradle file, also add the dependency inside the plugin section.
plugins { id("kotlinx-serialization")}Retrofit Helper Class
Your Retrofit helper class should be like below. Take note of the import statements.
import com.jakewharton.retrofit2.converter.kotlinx.serialization.asConverterFactoryimport kotlinx.serialization.json.Jsonimport okhttp3.MediaTypeimport retrofit2.Retrofit
object ApiHelper {
val baseApi = "https://api.somewebsite.com/" private val contentType = MediaType.get("application/json")
fun getInstance(): Retrofit { return Retrofit.Builder() .baseUrl(baseApi) .addConverterFactory(Json.asConverterFactory(contentType)) .build() }}Proguard rules
Don’t forget about the proguard rules.
-if @kotlinx.serialization.Serializable class **-keepclassmembers class <1> { static <1>$Companion Companion;}
# Keep `serializer()` on companion objects (both default and named) of serializable classes.-if @kotlinx.serialization.Serializable class ** { static **$* *;}-keepclassmembers class <2>$<3> { kotlinx.serialization.KSerializer serializer(...);}
# Keep `INSTANCE.serializer()` of serializable objects.-if @kotlinx.serialization.Serializable class ** { public static ** INSTANCE;}-keepclassmembers class <1> { public static <1> INSTANCE; kotlinx.serialization.KSerializer serializer(...);}
# @Serializable and @Polymorphic are used at runtime for polymorphic serialization.-keepattributes RuntimeVisibleAnnotations,AnnotationDefaultkotlinx.serialization.MissingFieldExceptionIn your data class, it might seem that adding a nullable type to your variable is enough.
@Serializabledata class User( @SerialName("user_id") val userId: Int?)It’s not. You need to add a default null value.
@Serializabledata class User( @SerialName("user_id") val userId: Int? = null)Shoutout to Jere Schneider and tyczj for the helpful answers that can’t be found anywhere on Android’s documentation.