8

我想让 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

4

1 回答 1

12

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

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

下面是一些示例代码:

实例创建者:

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);
于 2013-04-21T06:51:50.597 回答