GSON fromJson返回LinkedHashMap而不是EnumMap

时间:2013-04-21 04:13:31

标签: java gson

我想让gson能够返回一个EnumMap对象。我使用以下代码

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());
    }
}

但是,我得到以下

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

即使我使用了new TypeToken<EnumMap<Country, String>>(){}.getType()来特定我想要EnumMap而不是LinkedHashMap

如何让gson返回EnumMap

1 个答案:

答案 0 :(得分:10)

即使使用类型标记,Gson也只能将数据反序列化为具有默认构造函数的类。并且EnumMap没有一个(它需要使用其元素匹配的枚举类型进行实例化)。解决此问题的最简单方法是定义和使用InstanceCreator

  

实现此接口以创建未定义no-args构造函数的类的实例。如果您可以修改类,则应该添加私有或公共无参数构造函数。但是,对于库类(例如JDK类)或者没有源代码的第三方库,这是不可能的。在这种情况下,您应该为类定义实例创建者。在Gson能够使用它们之前,应该使用GsonBuilder.registerTypeAdapter(Type,Object)方法注册此接口的实现。

下面是一些示例代码:

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);