2013-06-21 23 views
8

私はカスタムJavaオブジェクトをシリアル化したいので、SharedPreferencesを使用してそれを保存し、別のアクティビティで取得することができます。私は永続的なストレージを必要としません、SharedPreferences、私は私のアプリケーションが閉じられるときにそれらを拭く。私は現在GSONを使っていますが、AndroidのSparseArrayタイプではうまく動作していないようです。SparseArrayをシリアライズ<T> with 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); 
} 

デシリアライズ:

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をキャストしたい理由は、私は私のプログラム全体で1を使用することはありません理解していません。 SparseArray<Part>に切り替える前に私はHashMap<Integer,Part>を持っていましたが、それに問題はありませんでした。 SparseArraysはGsonでサポートされていないのですか、または私の側にエラーがありますか?

編集:SparseArrayは正しくデシリアライズされているようですが、内部のオブジェクトは正しく表示されないようです。 LinkedTreeMapsの代わりに、これらはPartである必要があります。 enter image description here

+0

'SharedPreferences'は、(アプリケーションが強制終了されても)セッション全体で持続します。 [共有設定を使う](http://developer.android.com/guide/topics/data/data-storage。)を読んでください。html#pref) – Rajesh

+0

ええ、私はclear()で手動でそれらを拭きます。私はちょうどそれらを維持することは必要ではないことを指摘したいと思った。 – Lennart

+0

'SharedPreferences'はアクティビティ間でデータを共有するためのものではありません。詳細はhttp://stackoverflow.com/q/3549596/1321873をご覧ください。 – Rajesh

答えて

5

SparseArrayが正しく直列化復元ではなく オブジェクト内部に入ったようです。 LinkedTreeMapsではなく、 Partである必要があります。

SparseArrayは、オブジェクト(ないPart)を含んでいるのであなたの観察は、正しいこと、Gsonはあなたのオブジェクトタイプとしてパートを作るために任意の手掛かりを持っていません。したがって、その悪名高い内部のタイプとしてあなたのリストをマップしますLinkedTreeMap

これを解決するには、SparseArrayを使用できないと思います...または、retreivedParts.get(key).toString()を試してから、gsonを使用してオブジェクトを再度解析してください。

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

答えを受け入れるつもりです。私はSparseArraysをHashMapsに置き換えましたが、私のカスタムオブジェクトは、そのオプションを有効にしないと適切に非直列化されなかったので、 'Gson gson = new GsonBuilder()。enableComplexMapKeySerialization()。create()'を直列化する必要がありました。 – 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でこの例を見つけることができます。

P .:私は最適化されていないことを知っていますが、必要なものを達成するためのアイデアを示すための単なる例です。

+0

このコードは機能します。しかし、SparseArrayはParcable/Serializableではないので、私はまだ解決策として使用していません。したがって、私はそれをさまざまな活動やプロセスに回すことはかなり困難です。結局、私はHashMapに落ちる。 –

+0

今後のリファレンスを残すhttps://gist.github.com/dmarcato/6455221 – Javier

関連する問題