GSON

2013-06-21 9 views
8

के साथ एक स्पैर्सएरे को सीरियलाइज करना, मैं एक कस्टम जावा ऑब्जेक्ट को क्रमबद्ध करना चाहता हूं, इसलिए मैं इसे स्टोर करने के लिए SharedPreferences का उपयोग कर सकता हूं और इसे किसी अन्य गतिविधि में पुनः प्राप्त कर सकता हूं। मुझे लगातार भंडारण की आवश्यकता नहीं है, SharedPreferences, जब मेरा एप्लिकेशन बंद हो जाता है तो मैं उन्हें मिटा देता हूं। मैं वर्तमान में इसके लिए जीएसओएन का उपयोग कर रहा हूं, लेकिन यह एंड्रॉइड के स्पैर्सएरे प्रकार के साथ अच्छी तरह से काम नहीं कर रहा है। GSON

मेरे वस्तुओं:

public class PartProfile { 

private int gameId; 
// Some more primitives 
private SparseArray<Part> installedParts = new SparseArray<Part>(); 

// ... 
} 

public class Part { 
    private String partName; 
    // More primitives 
} 

क्रमबद्धता:

Type genericType = new TypeToken<PartProfile>() {}.getType(); 
String serializedProfile = Helpers.serializeWithJSON(installedParts, genericType); 
preferences.edit().putString("Parts", serializedProfile).commit(); 

serializeWithJSON():

public static String serializeWithJSON(Object o, Type genericType) { 
    Gson gson = new Gson(); 
    return gson.toJson(o, genericType); 
} 

Deserialization:

Type genericType = new TypeToken<PartProfile>() {}.getType(); 
PartProfile parts = gson.fromJson(preferences.getString("Parts", "PARTS_ERROR"), genericType); 

SparseArray<Part> retreivedParts = parts.getInstalledParts(); 
int key; 
for (int i = 0; i < retreivedParts.size(); i++) { 
    key = retreivedParts.keyAt(i); 
    // Exception here: 
    Part part = retreivedParts.get(key); 
    // ... 
} 

अपवाद:

java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to com.mypackage.objects.Part 

मुझे समझ नहीं आता क्यों Gson मेरी ऑब्जेक्ट में एक LinkedTreeMap कास्ट करने के लिए चाहता है, मैं अपने पूरे कार्यक्रम में से एक का उपयोग कभी नहीं। SparseArray<Part> पर स्विच करने से पहले मेरे पास HashMap<Integer,Part> था, और इसके साथ कभी भी समस्या नहीं थी। क्या स्पैसअरेज़ जीसन द्वारा समर्थित नहीं हैं, या क्या मेरी तरफ कोई त्रुटि है?

संपादित करें: ऐसा लगता है कि स्पैर्सएरे को सही ढंग से deserialized हो जाता है, लेकिन अंदर वस्तुओं नहीं। LinkedTreeMaps के बजाय, यह Part प्रकार का होना चाहिए। enter image description here

+0

'साझा किए गए संदर्भ' सत्रों में बने रहते हैं (भले ही एप्लिकेशन मारे गए हों)। पढ़ें [साझा प्राथमिकताओं का उपयोग] (http://developer.android.com/guide/topics/data/data- स्टोरेज।एचटीएमएल # pref) – Rajesh

+0

हाँ, लेकिन मैं उन्हें स्पष्ट रूप से स्पष्ट() से मिटा देता हूं। मैं बस यह इंगित करना चाहता था कि उनका पालन करना जरूरी नहीं है। – Lennart

+0

'साझा किए गए संदर्भ' गतिविधियों में डेटा साझा करने के लिए नहीं हैं। अधिक जानकारी के लिए कृपया http://stackoverflow.com/q/3549596/1321873 देखें। – Rajesh

उत्तर

5

ऐसा लगता है कि SparseArray सही ढंग से deserialized हो जाता है, लेकिन उनके भीतर वस्तुओं। LinkedTreeMaps के बजाय, यह भाग का होना चाहिए।

आपका अवलोकन, सही है के बाद से SparseArray वस्तु (नहीं Part) शामिल हैं, Gson अपने ऑब्जेक्ट प्रकार के रूप में भाग बनाने के लिए किसी भी सुराग नहीं होगा। इसलिए यह आपकी सूची को इसके कुख्यात आंतरिक प्रकार LinkedTreeMap के रूप में मानचित्रित करता है।

इसे हल करने के लिए, मुझे लगता है कि आप SparseArray का उपयोग करने में सक्षम नहीं होंगे ... या आप retreivedParts.get(key).toString() का प्रयास कर सकते हैं, फिर ऑब्जेक्ट को फिर से पार्स करने के लिए जीसन का उपयोग करें।

public class SparseArrayTypeAdapter<T> extends TypeAdapter<SparseArray<T>> { 

    private final Gson gson = new Gson(); 
    private final Class<T> classOfT; 
    private final Type typeOfSparseArrayOfT = new TypeToken<SparseArray<T>>() {}.getType(); 
    private final Type typeOfSparseArrayOfObject = new TypeToken<SparseArray<Object>>() {}.getType(); 

    public SparseArrayTypeAdapter(Class<T> classOfT) { 
     this.classOfT = classOfT; 
    } 

    @Override 
    public void write(JsonWriter jsonWriter, SparseArray<T> tSparseArray) throws IOException { 
     if (tSparseArray == null) { 
      jsonWriter.nullValue(); 
      return; 
     } 
     gson.toJson(gson.toJsonTree(tSparseArray, typeOfSparseArrayOfT), jsonWriter); 
    } 

    @Override 
    public SparseArray<T> read(JsonReader jsonReader) throws IOException { 
     if (jsonReader.peek() == JsonToken.NULL) { 
      jsonReader.nextNull(); 
      return null; 
     } 
     SparseArray<Object> temp = gson.fromJson(jsonReader, typeOfSparseArrayOfObject); 
     SparseArray<T> result = new SparseArray<T>(temp.size()); 
     int key; 
     JsonElement tElement; 
     for (int i = 0; i < temp.size(); i++) { 
      key = temp.keyAt(i); 
      tElement = gson.toJsonTree(temp.get(key)); 
      result.put(key, gson.fromJson(tElement, classOfT)); 
     } 
     return result; 
    } 

} 

और इसका इस्तेमाल करने में आप इसे रजिस्टर करने की आवश्यकता: लेकिन मैं इसे

+0

मैं आपका उत्तर स्वीकार करने जा रहा हूं, क्योंकि इसका उचित समाधान नहीं लगता है। मैंने अपने स्पैर्सएरेज़ को हैश मैप्स के साथ बदल दिया, लेकिन मुझे 'जीसन जीसन = नया जीसनबिल्डर() सक्षम करना था। सक्षम कॉम्प्लेक्स मैपकेरीरियलाइजेशन()। उन्हें क्रमबद्ध करने के लिए() 'बनाएं, क्योंकि किसी भी तरह से मेरी कस्टम ऑब्जेक्ट्स को उस विकल्प के बिना ठीक से deserialized नहीं किया गया था। – Lennart

12

सच वहाँ SparseArray के किसी भी प्रकार को क्रमानुसार करने का एक तरीका है कि ऐसा करने के लिए सक्षम है नहीं लगता है, यहां एक उदाहरण कोड है अपने Gson वस्तु, इस तरह में:

Type sparseArrayType = new TypeToken<SparseArray<MyCustomClass>>() {}.getType(); 
Gson gson = new GsonBuilder() 
    .registerTypeAdapter(sparseArrayType, new SparseArrayTypeAdapter<MyCustomClass>(MyCustomClass.class)) 
    .create(); 

आप this gist में इस उदाहरण मिल सकते हैं।

पीएस .: मुझे पता है कि यह बिल्कुल अनुकूलित नहीं है, लेकिन यह केवल एक उदाहरण है कि आपको जो चाहिए उसे प्राप्त करने के बारे में एक विचार दें।

+0

यह कोड काम करता है। हालांकि, मैं अभी भी इसे समाधान के रूप में उपयोग नहीं करता क्योंकि स्पैर्सएरे पारसीबल/सीरियलज़ेबल नहीं है। इसलिए, मेरे लिए इसे विभिन्न गतिविधियों और प्रक्रियाओं के आसपास पारित करना बहुत मुश्किल है। अंत में, मैं हैश मैप पर वापस आ गया। –

+0

मैं भविष्य का संदर्भ छोड़ दूंगा https://gist.github.com/dmarcato/6455221 – Javier