2013-04-21 3 views
6

gsonにEnumMapオブジェクトを返すようにします。私はLinkedHashMapGSON fromJson EnumMapの代わりにLinkedHashMapを返します

はどのように作ることができるEnumMap代わりにしたい私は、私は特定のnew TypeToken<EnumMap<Country, String>>(){}.getType()を使用していたにも関わらず、次の

toJSon : {"Malaysia":"RM","UnitedStates":"USD"} 
fromJSon : {Malaysia=RM, UnitedStates=USD} 
fromJSon : class java.util.LinkedHashMap 

を得ている、

package sandbox; 

import com.google.gson.Gson; 
import com.google.gson.reflect.TypeToken; 
import java.util.EnumMap; 
import java.util.Map; 

/** 
* 
* @author yccheok 
*/ 
public class Sandbox { 

    public static void main(String[] args) throws InterruptedException {  
     testGson(); 
    } 

    public static enum Country { 
     Malaysia, 
     UnitedStates 
    } 

    public static void testGson() { 
     Map<Country, String> enumMap = new EnumMap<Country, String>(Country.class); 
     enumMap.put(Country.Malaysia, "RM"); 
     enumMap.put(Country.UnitedStates, "USD"); 
     Gson gson = new Gson(); 
     String string = gson.toJson(enumMap); 
     System.out.println("toJSon : " + string); 
     enumMap = gson.fromJson(string, new TypeToken<EnumMap<Country, String>>(){}.getType()); 
     System.out.println("fromJSon : " + enumMap); 
     System.out.println("fromJSon : " + enumMap.getClass()); 
    } 
} 

ただし、次のコードを使用します返信するgson EnumMap

答えて

9

タイプトークンを使用しても、Gsonはデフォルトのコンストラクタを持つクラスにのみデータを逆シリアル化できます。 EnumMapには要素がありません(要素が一致する列挙型でインスタンス化する必要があります)。この問題を回避する最も簡単な方法は、InstanceCreatorを定義して使用することです:

このインタフェースは、引数なしのコンストラクタを定義していないクラスのインスタンスを作成するために実装されています。クラスを変更できる場合は、代わりに非公開のpublic no-argsコンストラクタを追加する必要があります。ただし、JDKクラスなどのライブラリクラスや、ソースコードを持たないサードパーティのライブラリでは不可能です。そのような場合は、クラスのインスタンス作成者を定義する必要があります。 Gsonがそれらを使用する前に、このインタフェースの実装をGsonBuilder.registerTypeAdapter(Type、Object)メソッドに登録する必要があります。

HERESにいくつかのサンプルコード:

InstanceCreator:

class EnumMapInstanceCreator<K extends Enum<K>, V> implements 
     InstanceCreator<EnumMap<K, V>> { 
    private final Class<K> enumClazz; 

    public EnumMapInstanceCreator(final Class<K> enumClazz) { 
     super(); 
     this.enumClazz = enumClazz; 
    } 

    @Override 
    public EnumMap<K, V> createInstance(final Type type) { 
     return new EnumMap<K, V>(enumClazz); 
    } 
} 

テストコード:

final Gson gson = new GsonBuilder().registerTypeAdapter(
     new TypeToken<EnumMap<Country, String>>() { 
     }.getType(), 
     new EnumMapInstanceCreator<Country, String>(Country.class)) 
     .create(); 

final Map<Country, String> enumMap = new EnumMap<Country, String>(
     Country.class); 
enumMap.put(Country.Malaysia, "RM"); 
enumMap.put(Country.UnitedStates, "USD"); 
String string = gson.toJson(enumMap); 
System.out.println("toJSon : " + string); 

final Map<Country, String> reverseEnumMap = gson.fromJson(string, 
     new TypeToken<EnumMap<Country, String>>() { 
     }.getType()); 
System.out.println("fromJSon (Class): " + reverseEnumMap.getClass()); 
System.out.println("fromJSon : " + reverseEnumMap); 
+0

はちょっと奇妙ですが、私は正確にあなたのコードを使用しますが、私はまだのLinkedHashMapを取得しています私の側で。私はgson-2.1を使用しています。それは問題ですか? –

+3

申し訳ありません。最新のgson 2.2.3を使うと完璧に動作します。 –

+1

@CheokYanCheng GSON 2.2.3を使用すると、コードを変更せずにすぐに使用できますか? –

関連する問題