当试图将EnumTypeAdapter与Proguard一起使用时,它会在gson.getAdapter()中导致AssertionError。此错误似乎是由于类型信息丢失...以下是所有相关源代码:
例外情况:
03-18 13:27:12.905: ERROR/roboguice(12139): Throwable caught during background processing
java.lang.AssertionError
at com.google.gson.internal.bind.TypeAdapters$EnumTypeAdapter.<init>(Unknown Source)
at com.google.gson.internal.bind.TypeAdapters$24.create(Unknown Source)
at com.google.gson.Gson.getAdapter(Unknown Source)
正在使用的EnumTypeAdapter:
public class OperationResultSerializer implements JsonDeserializer<OperationResult>, JsonSerializer<OperationResult> {
@Override
public OperationResult deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
int value = json.getAsJsonPrimitive().getAsInt();
return OperationResult.values()[value];
}
@Override
public JsonElement serialize(OperationResult src, Type typeOfSrc, JsonSerializationContext context) {
return new JsonPrimitive(src.ordinal());
}
}
如何构造GSON对象:
gson = new GsonBuilder()
.registerTypeAdapter(Calendar.class, new WcfCalendarSerializer())
.registerTypeAdapter(OperationResult.class, new OperationResultSerializer())
.registerTypeAdapter(FieldName.class, new FieldNameSerializer())
.registerTypeAdapter(MealType.class, new MealTypeSerializer())
.create();
我的ProGuard配置:
#-dontusemixedcaseclassnames: Necessary when building on windows where x.class and X.class is the same file
-dontusemixedcaseclassnames
-keepattributes *Annotation*
-keepattributes Signature
# Preserve the special static methods that are required in all enumeration classes.
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep public class * extends android.app.Application
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep class * extends android.view.View {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
-keep class com.google.inject.** { *; }
-keep class javax.inject.** { *; }
-keep class javax.annotation.** { *; }
-keep class roboguice.** { *; }
-keep class * extends android.preference.Preference {
public <init>(android.content.Context);
public <init>(android.content.Context, android.util.AttributeSet);
public <init>(android.content.Context, android.util.AttributeSet, int);
public void set*(...);
}
# Gson specific classes
-keep class sun.misc.Unsafe { *; }
#-keep class com.google.gson.stream.** { *; }
###Action bar sherlock
-keep class android.support.v4.app.** { *; }
-keep interface android.support.v4.app.** { *; }
-keep class com.actionbarsherlock.** { *; }
-keep interface com.actionbarsherlock.** { *; }
###RoboGuice
-keepclassmembers class * {
@com.google.inject.Inject <init>(...);
}
-keepclassmembers class * {
void *(**On*Event);
}
-keep public class roboguice.**
-keep class com.google.inject.**
-keep class com.google.gson.** {*;}
#datacontract
-keep public class com.ordering.datacontract.*
-keepclassmembers class com.ordering.datacontract.*
# LVL License binder class
-keep class com.android.vending.licensing.ILicensingService
-dontwarn
-ignorewarnings
如前所述,我怀疑由于丢失了类型信息而出现了故障--在深入研究了GSON源代码后,这是用来解析EnumTypeAdapter的代码...显然,getEnumConstants返回的名称不是作为CLASSoft类型的字段存在的。但我不确定这怎么可能。
private static final class EnumTypeAdapter<T extends Enum<T>> extends TypeAdapter<T> {
private final Map<String, T> nameToConstant = new HashMap<String, T>();
private final Map<T, String> constantToName = new HashMap<T, String>();
public EnumTypeAdapter(Class<T> classOfT) {
try {
for (T constant : classOfT.getEnumConstants()) {
String name = constant.name();
SerializedName annotation = classOfT.getField(name).getAnnotation(SerializedName.class);
if (annotation != null) {
name = annotation.value();
}
nameToConstant.put(name, constant);
constantToName.put(constant, name);
}
} catch (NoSuchFieldException e) {
throw new AssertionError();
}
}
public T read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
return nameToConstant.get(in.nextString());
}
public void write(JsonWriter out, T value) throws IOException {
out.value(value == null ? null : constantToName.get(value));
}
}
我到处寻找可能的解决办法,但没有找到太多的帮助。也许有人以前遇到过这种情况,可以给我指明正确的方向?
我通过并检查了反编译的结果APK。我相信这个问题与某些枚举类型在混淆过程中丢失其成员有关。
一定要保留枚举类成员:
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
另外-确保GSON中使用的所有类都被保留:
-keep public class com.company.ordering.datacontract.** {
public protected *;
}
-keep public class com.company.ordering.service.request.** {
public protected *;
}
-keep public class com.company.ordering.service.response.** {
public protected *;
}
在序列化/反序列化过程中,我的项目在中实现了一个,用于保留对象的多态性状态。不管怎样,该项目在开发测试中工作得很好,但当它用proguard混淆发布并测试时,它就崩溃了。 我的Gson特定的proguard配置是: 我正在使用的打字适配器是: 任何来自开发者社区的帮助都将不胜感激。
问题内容: 我正在处理一些服务器代码,其中客户端以JSON形式发送请求。我的问题是,有许多可能的请求,每个请求的实现细节都不尽相同。因此,我想使用一个Request接口,它定义为: 从那里,我在名为如下的类中实现了接口: 为了使用JSON,我创建了一个实例并注册了一个,如下所示: 然后,如下面的代码片段所示,我使用了它: 我得到了预期的输出。 我希望做的是用类似于以下内容的内容替换该行,但是这样做
我的适配器 我的持有者 类myHolder(itemView:View):recyclerview.viewholder(itemView){} 第二个 提前致谢
我有一个带有Spring(5.7.2)Web/Security的REST API项目。 我只有一个表,它包含一个id和一个名称。 当我删除光盘时,我的DiscsService会 当我需要插入或更新时,我会: 我了解到,当您希望在同一事务中使用值(提交之前)时,将使用,并且将同步并清空SQL缓存。 在我的例子中,我看到我在数据库中插入/更新或删除了值。 我应该使用flush()(我认为不应该),但可
问题内容: 我正在尝试创建一个通用类以与Google Gson一起使用。我已经创建了课程。此类具有以下方法: 目标是该方法应该能够与我设置了GsonJsonConverterImplementation的任何Type一起使用。不幸的是,它不起作用,也不能代替T 使用。我确信问题是由于我对Java泛型类型缺乏理解而引起的。在Gson上使用泛型的正确方法是什么? 使用Kris的答案进行 编辑,我认为这
问题内容: 我在应用程序中使用Gson,为此,我使用了一些名称与使用Json相同的类。我的应用程序运行良好,但是在编写proguard时,应用程序崩溃了,我猜有些类正在缩小。我的错误是: java.lang.ClassCastException:com.google.gson.internal.StringMap无法转换为com.sample.package.GsonClass 问题答案: 您需要