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的发布模式下运行时,哪条规则可能会丢失导致问题?
1条答案
按热度按时间tzcvj98z1#
当你应用R8/proguard时,它会重命名你所有的变量、类和方法等等。所以你可以做的就是添加你已经做过的必需的proguard规则。
我检查了你的proguard文件,我可以说你已经提供了足够的规则,但是如果你要反序列化的类在混淆过程中被重命名或删除了呢?
因此,您还必须为该类添加proguard规则。例如,如果你要传递任何模型类,那么你必须添加proguard规则来保持该类的完整性,或者在cariable名称前使用
@SerializedName("varName")
注解来拒绝该类中的变量的混淆。