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

6

44

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>
Vincent answered 24/4, 2022 at 11:56 Comment(0)
S
83

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

Shippee answered 31/5, 2022 at 17:15 Comment(5)
This helped hugely. Adding id 'kotlinx-serialization' to the app module's build.gradle file fixed for me.Kurbash
Note: ProGuard rules are now included as part of the library (first included in 1.5.0-RC), as mentioned in the readme. (Note that named companion objects are not included and still require additional configuration as mentioned)Goss
This answer applies maybe for an Android project, but for Ktor project it's not really relevant. The original question is about Ktor projectPremaxilla
I was following a Google course about Jetpack Compose and when I bumped into this issue I came here. I had to add id("org.jetbrains.kotlin.plugin.serialization") version "1.8.10" apply false to my build.gradle.kts (Project: MyProject) and everything worked fine, but I don't understand why Google hadn't added it here and everything still works as expected.Pinnace
Thank you for this answer. May angels reserve a place for you in heaven.Shayne
D
6

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}

Dapsang answered 12/1, 2024 at 12:8 Comment(0)
R
3

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"
Rheostat answered 7/1, 2024 at 6:30 Comment(0)
V
2

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

Vestavestal answered 24/4, 2022 at 14:53 Comment(5)
yeah, it is ktor app, and i am passing PaginatedResponse to call.respond(). And the thing that before the call of call.respond all the data is present there. will add screen shot to the question.Vincent
It also happened to me in my Kotlin JS application. This extension with retified is unbelivable dangerous, not a single warning in the docs or from the lint.Krystenkrystin
This problem or misconeption is rather related to the language feature of "reified types" and the nature of Kotlin's type inference. It applies for any other functions with reified type the same. It would be best to put it into the Kotlin docs kotlinlang.org/docs/…Vestavestal
How did you resolve your issue?Felker
Well I had to move the call of the respond function into the individual branches of the when statement, as this is where they still have their specific type information. So I had one "respond" per branch instead of one "respond" outside the branch.Vestavestal
M
0

Like the above answer, he may be missing the type

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

Mocha answered 18/7, 2023 at 8:26 Comment(0)
C
0

For me nothing helped, but adding these rules in proguard-rules.pro according to this link

-keep class * {
 @kotlinx.serialization.SerialName <fields>;
}

This became mandatory because of enabled R8 fullMode by default in gradle 8.

Caress answered 9/7, 2024 at 15:32 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.