Google Gson preserve generic signatures
Asked Answered
B

3

19

Crashes in Firebase Crashlytics appear with a note how to fix a problem:

Fatal Exception: java.lang.IllegalStateException: TypeToken must be created with a type argument: new TypeToken<...>() {}; When using code shrinkers (ProGuard, R8, ...) make sure that generic signatures are preserved.

My generic class between angle brackets <...> is named ApiResponse. I created it with jsonschema2pojo.

Boiardo answered 11/5, 2023 at 7:7 Comment(0)
B
41

An exclusion for serialized/deserialized classes over Gson is needed. For a package containing your classes looks like this

# Application classes that will be serialized/deserialized over Gson
-keep class com.myapplication.model.api.** { *; }

Also add this

# Gson uses generic type information stored in a class file when working with
# fields. Proguard removes such information by default, keep it.
-keepattributes Signature

# This is also needed for R8 in compat mode since multiple 
# optimizations will remove the generic signature such as class 
# merging and argument removal. See: 
# https://r8.googlesource.com/r8/+/refs/heads/main/compatibility-faq.md#troubleshooting-gson-gson
-keep class com.google.gson.reflect.TypeToken { *; }
-keep class * extends com.google.gson.reflect.TypeToken

# Optional. For using GSON @Expose annotation
-keepattributes AnnotationDefault,RuntimeVisibleAnnotations
-keep class com.google.gson.reflect.TypeToken { <fields>; } 
-keepclassmembers class **$TypeAdapterFactory { <fields>; }
Boiardo answered 11/5, 2023 at 7:7 Comment(6)
Are you sure this addressed the issue? Please also take a look at r8.googlesource.com/r8/+/refs/heads/main/…, where the TypeToken handling is explained.Paschall
Also see github.com/google/gson/pull/2397 for consumer rules being added to GSON.Paschall
Full proguard file: github.com/google/gson/blob/main/gson/src/main/resources/…Pamella
This is still not working for meCameron
-keep class com.google.gson.reflect.TypeToken { <fields>; } -keepclassmembers class **$TypeAdapterFactory { <fields>; }Slumber
@VurgunM i will add thisBoiardo
S
0

If you are using serialize name to like

@Keep
data class TagModel(
    @SerializedName("created_by") val createdBy: String,
    val name: String,
    val created: Long = System.currentTimeMillis(),
) {
    val formattedTime: String
        get() = created.convertLongToTime(DateFormat.DD_MMM_YYYY.format)

}

@Keep
data class ResearchModel(
    val title: String? = null,
    val description: String? = null,
    @PropertyName("created_by") @get:PropertyName("created_by") val createdBy: String? = null,
    @PropertyName("created_by_uid") @get:PropertyName("created_by_uid") val createdByUID: String? = null,
    val created: Long? = null,
    @PropertyName("dead_line") @get:PropertyName("dead_line") val deadLine: Long? = null,
    val tags: String? = null,
    val key: String? = null
) {
    val formattedTime: String
        get() = created?.convertLongToTime(DateFormat.DD_MMM_YYYY.format) ?: "No Date"

    val formattedDeadline: String
        get() = deadLine?.convertLongToTime(DateFormat.DD_MMM_YYYY.format) ?: "No Deadline"
}
inline fun <reified T> fromJsonList(json: String): List<T> {
    val gson = Gson()
    val type = object : TypeToken<List<T>>() {}.type
    return gson.fromJson(json, type)
}

you can use

-keep class com.google.gson.reflect.TypeToken { *; }
-keep class * extends com.google.gson.reflect.TypeToken

# Optional. For using GSON @Expose annotation
-keepattributes AnnotationDefault,RuntimeVisibleAnnotations

-keepattributes Signature
-keepclassmembers class * {
  @com.google.gson.annotations.SerializedName <fields>;
}
-keep class com.atech.core.model.** { *; }
-keep class com.atech.core.utils.JsonKt { *; }
Stereotaxis answered 18/5 at 8:50 Comment(0)
D
0

All of these proguard rules has been added automatically on Gson 2.11.0

so just upgrade the Gson dependency

Delora answered 30/7 at 17:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.