使用 Proguard 优化后,Jackson Json 解析器在 Android 上的所有对象成员上返回 null
我有一个 Android 应用程序,它使用 Jackson 解析器进行 JSON 解析。在我对类运行 Proguard 后,我开始在反序列化类的每个成员上获取 null 值。 例如,如果我有一个对象:
public class Service{
private String name;
private String version;
... getters, setters and stuff
}
并且收到一个包含这些对象列表的 JSON:
[{"name":"service1","version":"1.1"},{"name":"service2","version":"1.0"}]
那么我会这样做:
objectMapper.readValue(jsonString,new TypeReference<List<Service>>() {})
我得到的是一个包含 2 个 Service
对象的列表,其中所有成员均为 null。
有什么想法吗?
谢谢
更新,
我错过了 ProGuard 警告:
org.codehaus.jackson.map.deser.EnumSetDeserializer: can't find referenced method 'EnumDeserializer(org.codehaus.jackson.map.deser.EnumResolver)' in class org.codehaus.jackson.map.deser.EnumDeserializer
org.codehaus.jackson.map.deser.impl.StringCollectionDeserializer: can't find referenced method 'org.codehaus.jackson.map.JsonMappingException instantiationException(java.lang.Class,java.lang.Exception)' in class org.codehaus.jackson.map.DeserializationContext
用以下命令修复了这些警告:
-dontskipnonpubliclibraryclassmembers
就这样了。
亚历克斯
·P.S.
这是proguard.conf,所有库都是通过Maven插件添加的
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-dontoptimize
-dontnote
-dontskipnonpubliclibraryclasses
-printmapping map.txt
-printseeds seed.txt
-ignorewarnings
-keepclassmembers class * { @com.google.api.client.util.Key <fields>;}
-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault
-keepattributes *Annotation*
-keepclasseswithmembers public class * { public static void main(java.lang.String[]);}
-keepclassmembers public class com.anydo.client.model** { * ; }
-keepclassmembers public class com.anydo.common.dto** { * ;}
-keep class com.j256.** {*;}
-dontskipnonpubliclibraryclassmembers
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keepclassmembers class **.R$* {
public static <fields>;
}
#ACRA
-keep class org.acra.ACRA {
*;
}
# keep this around for some enums that ACRA needs
-keep class org.acra.ReportingInteractionMode { *; }
# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter
{
public void addCustomData(java.lang.String,java.lang.String);
}
# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter
{
public org.acra.ErrorReporter$ReportsSenderWorker handleSilentException(java.lang.Throwable);
}
I have an Android app which uses Jackson parser for JSON parsing. After I've ran Proguard on the classes I started to get null
values on each and every member of the de-serialized classes.
For example, if I have a object:
public class Service{
private String name;
private String version;
... getters, setters and stuff
}
and I receive a JSON with list of those objects:
[{"name":"service1","version":"1.1"},{"name":"service2","version":"1.0"}]
then I do:
objectMapper.readValue(jsonString,new TypeReference<List<Service>>() {})
what I get is a list with 2 Service
objects where all members are null.
Any ideas?
Thanks
UPDATE
I've missed ProGuard warnings:
org.codehaus.jackson.map.deser.EnumSetDeserializer: can't find referenced method 'EnumDeserializer(org.codehaus.jackson.map.deser.EnumResolver)' in class org.codehaus.jackson.map.deser.EnumDeserializer
org.codehaus.jackson.map.deser.impl.StringCollectionDeserializer: can't find referenced method 'org.codehaus.jackson.map.JsonMappingException instantiationException(java.lang.Class,java.lang.Exception)' in class org.codehaus.jackson.map.DeserializationContext
fixed those with:
-dontskipnonpubliclibraryclassmembers
and that did it.
Alex
P.S.
Here's the proguard.conf, all the libraries are added by Maven plugin
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-dontoptimize
-dontnote
-dontskipnonpubliclibraryclasses
-printmapping map.txt
-printseeds seed.txt
-ignorewarnings
-keepclassmembers class * { @com.google.api.client.util.Key <fields>;}
-keepattributes Signature,RuntimeVisibleAnnotations,AnnotationDefault
-keepattributes *Annotation*
-keepclasseswithmembers public class * { public static void main(java.lang.String[]);}
-keepclassmembers public class com.anydo.client.model** { * ; }
-keepclassmembers public class com.anydo.common.dto** { * ;}
-keep class com.j256.** {*;}
-dontskipnonpubliclibraryclassmembers
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembernames class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}
-keepclassmembers class **.R$* {
public static <fields>;
}
#ACRA
-keep class org.acra.ACRA {
*;
}
# keep this around for some enums that ACRA needs
-keep class org.acra.ReportingInteractionMode { *; }
# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter
{
public void addCustomData(java.lang.String,java.lang.String);
}
# keep this otherwise it is removed by ProGuard
-keep public class org.acra.ErrorReporter
{
public org.acra.ErrorReporter$ReportsSenderWorker handleSilentException(java.lang.Throwable);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
看起来您正在将不同版本的 jackson-mapper jar 组合到一个项目中。
jackson-mapper-asl-1.7.9.jar 包含
EnumDeserializer(org.codehaus.jackson.map.deser.EnumResolver)
jackson-mapper-asl-1.9.2.jar 包含
EnumDeserializer(org.codehaus.jackson.map.util.EnumResolver)
请注意 EnumSetDeserializer 的不同包和 EnumDeserializer 的不同构造函数。 ProGuard 无法解析 1.7.9 EnumSetDeserializer 对同一类路径上 1.9.2 EnumDeserializer 的构造函数的引用,并且它正确地对此发出警告。
It looks like you're combining different versions of the jackson-mapper jar in a single project.
jackson-mapper-asl-1.7.9.jar contains
EnumDeserializer(org.codehaus.jackson.map.deser.EnumResolver)
jackson-mapper-asl-1.9.2.jar contains
EnumDeserializer(org.codehaus.jackson.map.util.EnumResolver)
Notice the different packages for EnumSetDeserializer and the different constructors for EnumDeserializer. ProGuard can't resolve the reference of the 1.7.9 EnumSetDeserializer to the constructor of the 1.9.2 EnumDeserializer on the same class path, and it rightly warns about it.