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

35.4k Views Asked by At

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 enter image description here 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>
5

There are 5 best solutions below

5
On BEST ANSWER

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

5
On

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

0
On

Like the above answer, he may be missing the type

I solved this by adding <reified T> on the sub method.

0
On

Only implementation library is not enough, you still need the plugin. Therefore we need all belowings:

app/build.gradle:

1 implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.6.0")

2 plugins { id "org.jetbrains.kotlin.plugin.serialization" }

build.gradle:

3 plugins { id "org.jetbrains.kotlin.plugin.serialization" version "1.8.20" apply false}

0
On

I solved the issue by adding the plugin below in the gradle.app plugins block

id ("kotlinx-serialization")

This works if you have the kotlinx serialization plugin in the build.gradle.kts (Module :app) plugin block

id("org.jetbrains.kotlin.plugin.serialization") version "1.8.10"