2013-03-21 9 views
35

का उपयोग करते समय Gson EnumTypeAdapter में AssertionError ऑब्जेक्ट के polymorphism स्थिति को संरक्षित करने के लिए serialization/deserialization के दौरान Gson में मेरी परियोजना TypeAdapter लागू करती है। किसी भी तरह, परियोजना विकास परीक्षणों के दौरान ठीक काम करती है, लेकिन जब इसे प्रोजेवार्ड obfuscation के साथ जारी किया जाता है और परीक्षण किया जाता है, तो यह केवल दुर्घटनाग्रस्त हो जाता है।प्रोजेवार्ड Obfuscation

03-21 10:06:53.632: E/AndroidRuntime(12441): FATAL EXCEPTION: main 
03-21 10:06:53.632: E/AndroidRuntime(12441): java.lang.AssertionError 
03-21 10:06:53.632: E/AndroidRuntime(12441): at com.google.gson.internal.bind.TypeAdapters$EnumTypeAdapter.<init>(SourceFile:724) 
03-21 10:06:53.632: E/AndroidRuntime(12441): at com.google.gson.internal.bind.TypeAdapters$26.create(SourceFile:753) 
03-21 10:06:53.632: E/AndroidRuntime(12441): at com.google.gson.Gson.getAdapter(SourceFile:353) 
03-21 10:06:53.632: E/AndroidRuntime(12441): at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.<init>(SourceFile:82) 
03-21 10:06:53.632: E/AndroidRuntime(12441): at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.createBoundField(SourceFile:81) 
03-21 10:06:53.632: E/AndroidRuntime(12441): at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.getBoundFields(SourceFile:118) 
03-21 10:06:53.632: E/AndroidRuntime(12441): at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory.create(SourceFile:72) 
03-21 10:06:53.632: E/AndroidRuntime(12441): at com.google.gson.Gson.getAdapter(SourceFile:353) 
03-21 10:06:53.632: E/AndroidRuntime(12441): at com.google.gson.Gson.toJson(SourceFile:578) 
03-21 10:06:53.632: E/AndroidRuntime(12441): at com.google.gson.Gson.toJsonTree(SourceFile:479) 
03-21 10:06:53.632: E/AndroidRuntime(12441): at com.google.gson.Gson.toJsonTree(SourceFile:458) 
03-21 10:06:53.632: E/AndroidRuntime(12441): at com.google.gson.Gson$3.serialize(SourceFile:137) 

मेरे Gson विशिष्ट ProGuard विन्यास है:

##---------------Begin: proguard configuration for Gson ---------- 
# Gson uses generic type information stored in a class file when working with fields. Proguard 
# removes such information by default, so configure it to keep all of it. 
-keepattributes Signature 

# For using GSON @Expose annotation 
-keepattributes *Annotation* 

# Gson specific classes 
-keep class sun.misc.Unsafe { *; } 
#-keep class com.google.gson.stream.** { *; } 

# Application classes that will be serialized/deserialized over Gson 
-keep class com.google.gson.examples.android.model.** { *; } 

#This is extra - added by me to exclude gson obfuscation 
-keep class com.google.gson.** { *; } 

##---------------End: proguard configuration for Gson ---------- 

TypeAdapter मैं उपयोग कर रहा हूँ है:

public final class GsonWorkshiftAdapter implements JsonSerializer<IWorkshift>, JsonDeserializer<IWorkshift> { 
    private static final String CLASSNAME = "CLASSNAME"; 
    private static final String INSTANCE = "INSTANCE"; 

    @Override 
    public JsonElement serialize(IWorkshift src, Type typeOfSrc, JsonSerializationContext context) { 
     String className = src.getClass().getCanonicalName(); 
     JsonElement elem = context.serialize(src); 

     JsonObject retValue = new JsonObject(); 
     retValue.addProperty(CLASSNAME, className); 
     retValue.add(INSTANCE, elem); 

     return retValue; 
    } 

    @Override 
    public IWorkshift deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
     JsonObject jsonObject = json.getAsJsonObject(); 
     JsonPrimitive prim = (JsonPrimitive) jsonObject.get(CLASSNAME); 
     String className = prim.getAsString(); 

     Class<?> klass = null; 
     try { klass = Class.forName(className); } 
     catch (ClassNotFoundException e) { throw new JsonParseException(e.getMessage()); } 

     return context.deserialize(jsonObject.get(INSTANCE), klass); 
    } 
} 

मैं Gson के लिए विशिष्ट इस त्रुटि पर खोज की एक बहुत कुछ किया , लेकिन कोई उपयोगी जवाब नहीं मिला। हालांकि मुझे इसी तरह के मुद्दे के साथ another question मिला।

डेवलपर समुदाय से कोई भी मदद की सराहना की जाएगी।

+0

काश मैं इस सवाल का 100 बार वोट दें सकता है। मैं अंत में उत्पादन में अपने ऐप क्रैश को हल करने में सक्षम था, और साथ ही साथ enums और proguard के बारे में कुछ और सीखना। महान प्रश्न और उन सभी के लिए धन्यवाद जिन्होंने विवरण के साथ बहुत अच्छे जवाब पोस्ट किए हैं। @Eric Lafortune – Brandon

उत्तर

5

एक ही समस्या में भाग लेने के बाद, मैंने परिणामस्वरूप एपीके को संकुचित कर दिया और जांच की। मेरा मानना ​​है कि समस्या कुछ enum प्रकार से संबंधित है जो obfuscation के दौरान अपने सदस्यों को खोने।

-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 *; 
} 

पूर्ण config देखें @ pastebin.com/r5Jg3yY2

: - सुनिश्चित करें कि कक्षाओं के सभी GSON में इस्तेमाल किया जा रहा बनाए रखा जा रहा है बनाने के

-keepclassmembers enum * { 
    public static **[] values(); 
    public static ** valueOf(java.lang.String); 
} 

इसके अलावा:

enums रखना सुनिश्चित करें

16

जीएसओएन इस AssertionError को फेंकता है जब यह जेनॉन डेटा से गणना स्थिरांक को deserialize करने में विफल रहता है, enum वर्ग के क्षेत्रों पर आत्मनिरीक्षण प्रदर्शन। दुर्भाग्य से, यह अंतर्निहित NoSuchFieldException के विवरण निगलता है।

आपको यह सुनिश्चित करना चाहिए कि आप enum फ़ील्ड (और सामान्य रूप से फ़ील्ड्स) के नामों को संरक्षित करें जो क्रमबद्ध हैं। डिफ़ॉल्ट रूप से, ProGuard उनका नाम बदल सकता है या उन्हें हटा भी सकता है। उदाहरण के लिए, कुछ वाइल्डकार्ड के साथ के लिए:

-keepclassmembers class com.example.domain.** { 
    <fields>; 
} 
+9

enum फ़ील्ड के नामों के लिए प्लेसहोल्डर '' है, या इसे लिखा जाना चाहिए? –

+10

जैसा है: , , , **, *, और? ProGuard पहचानता है कि वाइल्डकार्ड हैं। –

+0

मेरी इच्छा है कि जीसन ने वही काम करने के लिए एक कम बेवकूफ तरीका इस्तेमाल किया होगा। यानी, फ़ील्ड को फिर से भरें और नाम प्राप्त करें, यह मानने के बजाय कि नाम रनटाइम पर फ़ील्ड नाम से मेल खाता है। – Trejkaz

9

यह पहले से ही सुझाव दिया है कि आप एक तरीका है कि यह बरकरार धारावाहिक वस्तुओं से जुड़ी हर छोटी enum रहता में Proguard विन्यस्त करने की जरूरत। मुझे वास्तव में यह तथ्य पसंद नहीं है कि मुझे अपने सभी enums को स्पष्ट रूप से सूचीबद्ध करना है, इस समाधान को बनाए रखना मुश्किल है। मेरे साथ आया थोड़ा बेहतर समाधान निम्नलिखित है।

एक खाली इंटरफ़ेस का उपयोग संकेत मिलता है कि एक वर्ग या enum Gson क्रमबद्धता में भाग लेता है:

public interface GsonSerializable { } 

public class MyClass implements GsonSerializable { 

    public enum MyEnum implements GsonSerializable { 
     enumvalue1, enumvalue2 
    } 

    public MyEnum mydata1; 
} 

उपयोग एक Proguard config कि दोनों इंटरफेस और सभी वर्गों/enums कि इसे लागू रहता है:

# keep GsonSerializable interface, it would be thrown away by proguard since it is empty 
-keep class com.example.GsonSerializable 

# member fields of serialized classes, including enums that implement this interface 
-keepclassmembers class * implements com.example.GsonSerializable { 
    <fields>; 
} 

# also keep names of these classes. not required, but just in case. 
-keepnames class * implements com.example.GsonSerializable 

यह तब तक है जब तक आपकी कक्षाएं और enums इंटरफ़ेस का उपयोग करते हैं, आपको ठीक होना चाहिए।आप भी अपनी क्रमबद्धता/अक्रमांकन तरीकों में इस इंटरफेस की उपस्थिति को लागू कर सकता है, तो आप इसे भूल नहीं है जब एक नया वर्ग बाद में जोड़ने: 'com.google.gson साथ

public String serializeWithGson(GsonSerializable object) { ... } 
अपने विन्यास में

इसके अलावा लाइन .examples.android.model। ** {*; } 'कुछ Google संबंधित उदाहरण कोड को संदर्भित करता है, इसलिए मुझे नहीं लगता कि यह आवश्यक है।

4

मेरे मामले में, ProGuard -keep व्यक्ति Gson से छुआ वर्गों के लिए कॉन्फ़िगर किया गया था, लेकिन त्रुटि दूर चला गया जब मैं ProGuard कॉन्फ़िगर किया गया पैकेज जहां उन अलग अलग वर्गों रहते बनाए रखने के लिए:

-keep class com.company.library.model.** { *; } 
80

यह की तरह लगता है हमें अनुरोध करना होगा कि गणना के सदस्यों को रखा गया है। यह मेरे लिए काम किया:

-keepclassmembers enum * { *; } 

या, यदि आप अधिक विशिष्ट होना चाहते हैं,

-keepclassmembers enum com.your.package.** { *; } 
+4

यह जवाब होना चाहिए, यह सटीक अपवाद का संदर्भ दे रहा है। धन्यवाद! –

+1

अंगूठे ऊपर (वाई), आपने मेरी समस्या हल की। –

+0

सही उत्तर, लेकिन क्या आप कृपया कारण बता सकते हैं? धन्यवाद – Xiaogegexiao

संबंधित मुद्दे