-
Notifications
You must be signed in to change notification settings - Fork 617
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Generic custom serializer breaks kotlin-kapt compilation #685
Comments
Just confirmed this still occurs with Kotlin 1.3.71 and a runtime version of 0.20.0. I can also upload a test project if that would be helpful! |
Worked around this by moving all network code into a separate module with no kapt plugin. |
Did some more investigation, and I believe this is the same issue as https://youtrack.jetbrains.com/issue/KT-30346, so that would make this firmly a In https://github.com/JetBrains/kotlin, there's two commits that reference the issue, Not sure what the relevant priority is, but I'm going to link this issue on https://youtrack.jetbrains.com/issue/KT-30346. |
I am getting an issue similar to this. I am using databinding and kotlinx.serialization.
But when I tried to build the project, the console printed the following error:
This didn't happen when I disabled the databinding.
or
But none of the solutions solves the original problem completely. |
I have the same issue as @eugenio1590 describes. I have the following enum with a @Serializable
enum class ReportStatus(val order: Int) {
@SerialName("E")
ERROR(-1),
@SerialName("O")
OPEN(0),
@SerialName("D")
@JsonNames("A", "N") // Decode the A and N values as FINAL.
FINAL(2),
} This causes the build to fail:
If i remove the second value of @SerialName("D")
@JsonNames("A", "N") // Decode the A and N values as FINAL.
FINAL(2), |
Any updates on the feature above? |
Can confirm we've hit the same roadblock with multiple |
We also encountered the same problem while using @Serializable
data class A(val p1: Int, val p2: Float)
@Serializable
data class B(
@JsonNames("id1", "id2") // this is ok, compile passed.
val id: String,
@JsonNames("result1", "result2") // compile error!
val result: List<A>,
) |
Seems there is kind of a workaround for this problem (using generic serializer, and not creating a typed version of it for each type parameter). typealias SafeList<T> = @Serializable(with = SafeListSerializer::class) KindListWrapper<T> where the implementations are as follows: KindListWrapper implementation
class KindListWrapper<T : Any>(private val list: List<T>) : List<T> by list {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as KindListWrapper<*>
if (list != other.list) return false
return true
}
override fun hashCode(): Int {
return list.hashCode()
}
override fun toString(): String {
return list.toString()
}
} SafeListSerializer implementation
@OptIn(ExperimentalSerializationApi::class)
@Serializer(forClass = KindListWrapper::class)
class SafeListSerializer<T : Any>(
private val valueSerializer: KSerializer<T>,
) : KSerializer<KindListWrapper<T>> {
private var throwableHandler: ((Throwable) -> Unit)? = null
constructor(elementSerializer: KSerializer<T>, throwableHandler: ((Throwable) -> Unit)?) : this(
elementSerializer
) {
this.throwableHandler = throwableHandler
}
private val listSerializer = ListSerializer(valueSerializer)
override val descriptor: SerialDescriptor = listSerializer.descriptor
override fun deserialize(decoder: Decoder): KindListWrapper<T> {
val values = mutableListOf<T?>()
val compositeDecoder = decoder.beginStructure(descriptor)
while (true) {
val index = compositeDecoder.decodeElementIndex(descriptor)
if (index == CompositeDecoder.DECODE_DONE) break
values.add(readElement(compositeDecoder))
}
compositeDecoder.endStructure(descriptor)
return KindListWrapper(values.filterNotNull())
}
override fun serialize(encoder: Encoder, value: KindListWrapper<T>) {
listSerializer.serialize(encoder, value)
}
private fun readElement(compositeDecoder: CompositeDecoder): T? {
return try {
val jsonDecoder = compositeDecoder as JsonDecoder
val jsonElement = jsonDecoder.decodeJsonElement()
jsonDecoder.json.decodeFromJsonElement(valueSerializer, jsonElement)
} catch (e: Exception) {
throwableHandler?.invoke(e)
null
}
}
} Solution is based on answers from discussion #1205 , specifically on this and this |
MisterPotz hello! I have used your solution so far, and find out the following problem. When we use SafeList in nested way, like here: @Serializable
data class Contact(
val name: String,
val phone: String
)
@Serializable
data class User(
val contacts: SafeList<Contact>
)
@Serializable
data class Response(
val result: SafeList<User>
) So, if we try to decode json like this: {
"result": [
{
"contacts": [
{
"name": "David",
"phone": "123"
},
{
"name": "John",
"phone": "456"
}
]
},
{
"contacts": [
{
"name": "George",
"phone": "321"
},
{
"name": "Lucas",
"phone": "654"
}
]
}
]
} we will face strange behaviour:
|
this solution (about custom serializer SafeListSerializerStack) is pretty forward, it worked for me |
Describe the bug
When using a generic custom serializer (see example below), adding the
kotlin-kapt
plugin with something that useskapt
(like data binding or Dagger) causes a Kotlin compiler error.To Reproduce
The following generic custom serializer works as expected in an Android project when
kotlin-kapt
is not in use:However, adding
and
causes building the build to fail with the following compiler exception:
Expected behavior
Applying the
kotlin-kapt
plugin shouldn't cause a compiler error.As a temporary workaround, specifying the type does allow compilation with
kotlin-kapt
, but this isn't ideal as it requires a separate class for every serialized type:Environment
The text was updated successfully, but these errors were encountered: