使用Gson从kotlinx集合反序列化ImmutableList

hpxqektj  于 2023-05-22  发布在  Kotlin
关注(0)|答案(1)|浏览(196)

bounty还有4天到期。回答此问题可获得+100声望奖励。Phil希望引起更多关注这个问题。

我试图在一个Android项目中使用Gson反序列化kotlinx.collections库中的ImmutableList。由于不同的项目相关原因,我还不能使用Kotlin序列化。
我为Gson定制的JsonDeserializer看起来像这样:

class ImmutableListDeserializer : JsonDeserializer<ImmutableList<*>> {

    @Throws(JsonParseException::class)
    @Suppress("UnstableApiUsage")
    override fun deserialize(
        json: JsonElement,
        type: Type,
        context: JsonDeserializationContext
    ): ImmutableList<*> {
        val typeArguments = (type as ParameterizedType).actualTypeArguments
        val parameterizedType: Type = listOf<Any>(typeArguments[0]).type
        val list = context.deserialize<List<*>>(json, parameterizedType)
        return list.toImmutableList()
    }

    @Suppress("UnstableApiUsage", "UNCHECKED_CAST")
    private fun <E> listOf(arg: Type): TypeToken<List<E>> = object : TypeToken<List<E>>() {}
        .where(object : TypeParameter<E>() {}, TypeToken.of(arg) as TypeToken<E>)
}

并且经由.registerTypeAdapter(ImmutableList::class.java, ImmutableListDeserializer())被添加到GsonBuilder
只要R8没有被激活,这就可以正常工作。调试变体)。当我使用R8时(特别是在完整模式下,这是AGP 8.0以来的新默认模式),我在尝试调用gson.fromJson(json, DataClassContainingImmutableList::class.java)时看到以下错误:

java.lang.ArrayIndexOutOfBoundsException: length=0; index=0
    at com.myapp.serialization.ImmutableListDeserializer.deserialize(ImmutableListDeserializer.kt:21)
    at com.myapp.serialization.ImmutableListDeserializer.deserialize(ImmutableListDeserializer.kt:11)
    at com.google.gson.internal.bind.TreeTypeAdapter.read(TreeTypeAdapter.java:76)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.readIntoField(ReflectiveTypeAdapterFactory.java:212)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$FieldReflectionAdapter.readField(ReflectiveTypeAdapterFactory.java:433)
    at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.read(ReflectiveTypeAdapterFactory.java:393)
    at com.google.gson.Gson.fromJson(Gson.java:1227)
    at com.google.gson.Gson.fromJson(Gson.java:1137)
    at com.google.gson.Gson.fromJson(Gson.java:1047)
    at com.google.gson.Gson.fromJson(Gson.java:982)

因此,错误位于这一行:
val parameterizedType: Type = listOf<Any>(typeArguments[0]).type
我在这里添加了所有的proguard / R8规则:https://github.com/google/gson/blob/master/examples/android-proguard-example/proguard.cfg以及一些附加的函数来保留自定义反序列化器中使用的Guava类:

-keep,allowobfuscation,allowshrinking class com.google.common.reflect.TypeToken { *; }
-keep,allowobfuscation,allowshrinking class * extends com.google.common.reflect.TypeToken
-keep,allowobfuscation,allowshrinking class com.google.common.reflect.TypeParameter { *; }
-keep,allowobfuscation,allowshrinking class * extends com.google.common.reflect.TypeParameter

有谁能告诉我,在R8的发布模式下运行时,哪条规则可能会丢失导致问题?

tzcvj98z

tzcvj98z1#

当你应用R8/proguard时,它会重命名你所有的变量、类和方法等等。所以你可以做的就是添加你已经做过的必需的proguard规则。
我检查了你的proguard文件,我可以说你已经提供了足够的规则,但是如果你要反序列化的类在混淆过程中被重命名或删除了呢?
因此,您还必须为该类添加proguard规则。例如,如果你要传递任何模型类,那么你必须添加proguard规则来保持该类的完整性,或者在cariable名称前使用@SerializedName("varName")注解来拒绝该类中的变量的混淆。

相关问题