I have a problem with the serialization of a class in Kotlin.
build.gradle.kt
...
plugins {
application
kotlin("jvm") version "1.6.21"
kotlin("plugin.serialization").version("1.6.21")
}
...
dependencies{
...
implementation("io.ktor:ktor-server-content-negotiation:$ktor_version")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktor_version")
}
Response.kt
import kotlinx.serialization.*
...
interface BaseResponse<T>
@Serializable
data class PaginatedResponse<T>(
val prev: Int?,
val next: Int?,
val totalCount: Int = 0,
val totalPages: Int = 0,
val data: T? = null,
val message: String? = null
) : BaseResponse<T>
usage
...
return PaginatedResponse<List<User>>(
prev,
next,
totalCount,
totalPages,
users
)
The data I am passing looks quite healthy and the error that is thrown when the return is reached is:
kotlinx.serialization.SerializationException: Serializer for class 'PaginatedResponse' is not found. Mark the class as @Serializable or provide the serializer explicitly.
Doing call.respond(User(...))
will not throw any error
so if I remove generic and make the PaginatedResponse non generic it will work but is not reusable anymore
@Serializable
data class PaginatedResponse(
val prev: Int?,
val next: Int?,
val totalCount: Long = 0,
val totalPages: Long = 0,
val data: List<User>? = null,
val message: String? = null
) : BaseResponse<User>
after reading some documentation I found that the error in my case was mainly due to two misconfigurations that I had:
first: I needed to add the plugin in the gradle at the app and project level, I solved this as follows:
adding in gradle.project the next line:
id 'org.jetbrains.kotlin.plugin.serialization' version '1.6.21'
As is seen in the following image:
and after that, adding in the gradle.app the next line in the plugins block : id 'kotlinx-serialization'
As is seen in the following image:
secondly, the problem was that when the classes were serialized at runtime, the proguard generated conflicts, for this I had to add a few lines to the file proguard-rules.pro
And add the following lines into the file:
### your config ....
# Keep `Companion` object fields of serializable classes.
# This avoids serializer lookup through `getDeclaredClasses` as done for named companion objects.
-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,AnnotationDefault
As is seen in the following image:
I finally synced the gradle, compiled again and everything worked fine.
Reference documentation: https://github.com/Kotlin/kotlinx.serialization#gradle-with-plugins-block