i use gson 2.8.5 in android project,run app with proguard on real Android Phone. when execute code Type listType = new TypeToken<List<T>>() {}.getType(),then crash:
java.lang.AssertionError: illegal type variable reference
at libcore.reflect.TypeVariableImpl.resolve(TypeVariableImpl.java:111)
at libcore.reflect.TypeVariableImpl.getGenericDeclaration(TypeVariableImpl.java:125)
at libcore.reflect.TypeVariableImpl.hashCode(TypeVariableImpl.java:47)
at java.util.Arrays.hashCode(Arrays.java:4153)
at com.google.gson.internal.$Gson$Types$ParameterizedTypeImpl.hashCode($Gson$Types.java:502)
at com.google.gson.reflect.TypeToken.<init>(TypeToken.java:64)
......
i have add these code in proguard.pro:
-keepattributes Exceptions
-keepattributes InnerClasses
-keepattributes Signature
-keepattributes Deprecated
-keepattributes SourceFile
-keepattributes LineNumberTable
-keepattributes *Annotation*
-keepattributes EnclosingMethod
# Gson specific classes
-keep class sun.** { *; }
#-keep class com.google.gson.stream.** { *; }
# Prevent proguard from stripping interface information from TypeAdapterFactory,
# JsonSerializer, JsonDeserializer instances (so they can be used in @JsonAdapter)
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
It doesn't look like a bug.listType cannot be declared with T (it looks like it's declared within your _generic class_ capturing the class type variable only) at the declaration site, but it should be declared at the call site with a real type, and then passed to your _generic class_. The same goes to generic methods. Simple googling before posting would save you some time and give some hints: Gson illegal type variable reference - Stack Overflow.
@lyubomyr-shaydariv maybe some other config cause this error. i config build.gradle
android {
buildTypes{
alpha {
minifyEnabled true
zipAlignEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro', 'proguard-rules-2.0.pro'
signingConfig signingConfigs.releaseConfig
multiDexKeepProguard file('keep_in_main_dex.pro')
debuggable = false
// matchingFallbacks属性来设置回退策略(必填,http://codezjx.com/2017/11/23/gradle-plugin-3-0-0-migration/)
matchingFallbacks = ['release']
}
}
}
the problem solve. But when config debuggable = ture, the error occur T_T.
I had the same problem
@kkmike999 Toggled debuggable not help us.
We convert a JSON string to List in our conditions. And then we got this error.
But same code in other computers works fine.
public static <T> List<T> jsonToList(@NonNull String jsonStr) {
try {
List<T> objList = null;
if (gson != null) {
Type type = new TypeToken<List<T>>() {}.getType();
objList = gson.fromJson(jsonStr, type);
}
return objList;
}catch (Exception e){
Log.i("json",e.getMessage());
return null;
}
}
We tried below code to fix it by specified a type.
public static <T> List<T> jsonToList(@NonNull String json, Class<T> cls) {
try {
Gson gson = new Gson();
List<T> list = new ArrayList<T>();
JsonArray array = new JsonParser().parse(json).getAsJsonArray();
for(final JsonElement elem : array){
list.add(gson.fromJson(elem, cls));
}
return list;
}catch (Exception e){
Log.i("json",e.getMessage());
return null;
}
}
Maybe it was compiled issue, hope it help.
Just using Gson in Retrofit converter:
api 'com.squareup.retrofit2:converter-gson:2.4.0'
Android Studio 3.6.1
Build #AI-192.7142.36.36.6241897, built on February 27, 2020
Runtime version: 1.8.0_212-release-1586-b04 amd64
VM: OpenJDK 64-Bit Server VM by JetBrains s.r.o
Windows 10 10.0
GC: ParNew, ConcurrentMarkSweep
Memory: 1979M
Cores: 12
Registry: ide.new.welcome.screen.force=true
Non-Bundled Plugins: String Manipulation, com.dengzii.plugin.adb, com.genymotion.idea, com.mfwebstudio.atomonedark.plugin.id, com.vermouthx.idea, net.seesharpsoft.intellij.plugins.file-preview, net.vektah.codeglance, cn.yiiguxing.plugin.translate, izhangzhihao.rainbow.brackets, BashSupport, com.developerphil.adbidea, some.awesome
@rosuH
No need to have it such complex. You can simply create a method like this:
public static <T> List<T> fromJsonToList(final String json, final Class<T> elementClass) {
return gson.fromJson(json, TypeToken.getParameterized(List.class, elementClass).getType());
}
that will do the job. I'd only recommend this method if you provide the element types dynamically, not statically (also note that gson can be re-used, no need to new it). However, I believe you only need something like this:
private static final TypeToken<List<Short>> listOfShorts = new TypeToken<List<Short>>() {};
private static final TypeToken<List<Float>> listOfFloats = new TypeToken<List<Float>>() {};
public static void main(final String... args) {
final String json = "[1,2,3,4,5,6]";
System.out.println(gson.<List<Short>>fromJson(json, listOfShorts.getType()));
System.out.println(gson.<List<Float>>fromJson(json, listOfFloats.getType()));
}
that would produce [1, 2, 3, 4, 5, 6] and [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] respectively. It is a little more verbose, but you don't need to implement custom methods, and you can reuse type tokens too.