Serializer for class '...' is not found. Mark the class as @Serializable or provide the serializer explicitly

Viewed 3374

Hi I have a problem with serialization of class in kotlin

build.gradl.kt

...
plugins {
    application
    kotlin("jvm") version "1.6.21"
    kotlin("plugin.serialization").version("1.6.21")
}
...
depenedancies{
...
    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
            )

data which I am passing looks quite healthy enter image description here and the error which is thrown when return is reached is next

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>
2 Answers

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: gradle.module

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: gradle.app

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 project tree

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:  file proguard-rules.pro

I finally synced the gradle, compiled again and everything worked fine.

Reference documentation: https://github.com/Kotlin/kotlinx.serialization#gradle-with-plugins-block

I once had a similar issue. I assume that you're using Ktor and the function returning the PaginatedReponse somehow gets passed as a parameter to call.respond(), right?

ApplicationCall.respond() is a reified inline function. In my case the variable I passed to call.respond() had lost it's static type information through a when-expression with multiple return types. The compiler inferred a common return type of the when expression of "Any".

In my case, this resulted in the same error message as you got there. Confusingly it said there was no serializer found for the specific type although the reified type was Any.

Perhaps you have the same issue as I did. Hope that I was able to help.

Definition of respond

Related