Kotlin / kotlinx.serialization

Kotlin multiplatform / multi-format serialization
Apache License 2.0
5.33k stars 618 forks source link

Update AGP 8.3.1 broken deserialization #2606

Open ravenfeld opened 5 months ago

ravenfeld commented 5 months ago

Hello, I have switched to agp 8.3.1 on my Android project and if I activate the minify I have the following problem.

kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 0: Serializer for subclass

I suppose it's the JSON I'm receiving because there's a key with "type" but it's not used for polymorphism. But what I don't understand is why it works fine without minify.

Thank you for your help.

Environment

sandwwraith commented 5 months ago

If this issue came from AGP configuration, it probably makes more sense to file it to the Google tracker (https://issuetracker.google.com/issues?q=Android%2F). Anyway, it is hard to understand what happened from a single exception message line. If you provide more information (stacktrace, @Serializable classes, project configuration, minimal reproducer), I might be able to help you.

ravenfeld commented 5 months ago

That's the mistake. For me it's a problem with proguard and with kotlin serialization because without proguard everything works fine.

Process: com.ravenfeld.maps, PID: 22963
                                                                                                    kotlinx.serialization.json.internal.JsonDecodingException: Unexpected JSON token at offset 0: Serializer for subclass 'FeatureCollection' is not found in the polymorphic scope of 'NetworkResponse' at path: $
                                                                                                    Check if class with serial name 'FeatureCollection' exists and serializer is registered in a corresponding SerializersModule.
                                                                                                    To be registered automatically, class 'FeatureCollection' has to be '@Serializable', and the base class 'NetworkResponse' has to be sealed and '@Serializable'.
                                                                                                    JSON input: {
                                                                                                      "type": "FeatureCollection.....
                                                                                                        at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
                                                                                                        at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
                                                                                                        at kotlinx.serialization.json.internal.AbstractJsonLexer.fail(AbstractJsonLexer.kt:598)
                                                                                                        at kotlinx.serialization.json.internal.AbstractJsonLexer.fail$default(AbstractJsonLexer.kt:596)
                                                                                                        at kotlinx.serialization.json.internal.StreamingJsonDecoder.decodeSerializableValue(StreamingJsonDecoder.kt:85)
                                                                                                        at kotlinx.serialization.json.Json.decodeFromString(Json.kt:107)
                                                                                                        at com.jakewharton.retrofit2.converter.kotlinx.serialization.Serializer$FromString.fromResponseBody(Serializer.kt:26)
                                                                                                        at com.jakewharton.retrofit2.converter.kotlinx.serialization.DeserializationStrategyConverter.convert(DeserializationStrategyConverter.kt:11)
                                                                                                        at com.jakewharton.retrofit2.converter.kotlinx.serialization.DeserializationStrategyConverter.convert(DeserializationStrategyConverter.kt:7)
                                                                                                        at retrofit2.OkHttpCall.parseResponse(OkHttpCall.java:246)
                                                                                                        at retrofit2.OkHttpCall$1.onResponse(OkHttpCall.java:156)
                                                                                                        at okhttp3.internal.connection.RealCall$AsyncCall.run(RealCall.kt:519)
                                                                                                        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
                                                                                                        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:644)
                                                                                                        at java.lang.Thread.run(Thread.java:1012)
                                                                                                        Suppressed: kotlinx.coroutines.internal.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@f901192, Dispatchers.Main.immediate]
ravenfeld commented 5 months ago

For information, no problem with version 7.4.2, but as of version 8.0.0 of gralde I have the problem.

sandwwraith commented 5 months ago

It's hard to say this without classes definitions and other setup, but maybe Proguard config is too aggressive and cuts off either your polymorphic module or NetworkResponse serializer completely. Try to add it to keep section of proguard.

ravenfeld commented 5 months ago

Yes, it must be too aggressive because it works with this. android.enableR8.fullMode=false

sandwwraith commented 5 months ago

Rules supplied by the library should work with full mode, too. Do you have any named companions? (companion object Foo { ... }). Maybe these configurations may help you: https://github.com/Kotlin/kotlinx.serialization/issues/2050#issuecomment-1274445927, https://github.com/Kotlin/kotlinx.serialization?tab=readme-ov-file#android — see 'Example of named companion rules for R8 full mode'

kodebach commented 4 months ago

We also experienced this issue in our app. I don't have a reproduction sample, but I fairly certain that this is an AGP issue.

We noticed the issue in our latest release, which upgrades AGP from 8.2.1 to 8.4.0. I can also confirm that the issue only happens with R8 "full mode" enabled and we do not use any named companion objects. We also more or less confirmed that the issue is only caused by the AGP 8.4.0 upgrade with "full mode" enabled and not by the Kotlin or kotlinx-serialization version changes in our latest app update.

I reported the issue to Google at https://issuetracker.google.com/issues/340494391