来自Json的GSON返回LinkedHashMap而不是EnumMap [英] GSON fromJson return LinkedHashMap instead of EnumMap

查看:242
本文介绍了来自Json的GSON返回LinkedHashMap而不是EnumMap的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想让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 static void main (String [] args)throws InterruptedException {
testGson();


public static enum Country {
Malaysia,
UnitedStates
}

public static void testGson(){
地图< 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

即使我有使用新TypeToken< EnumMap< Country,String>>(){}。getType()指定我想 EnumMap 而不是 LinkedHashMap



如何让gson返回 EnumMap

解决方案

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


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


Heres一些示例代码:

InstanceCreator:

  class EnumMapInstanceCreator< K extends Enum< K>,V>实现
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类型){
返回新的EnumMap< K,V>(enumClazz);


测试代码:

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

最终地图< 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);

最终地图< Country,String> reverseEnumMap = gson.fromJson(string,
new TypeToken< EnumMap< Country,String>>(){
} .getType());
System.out.println(fromJSon(Class):+ reverseEnumMap.getClass());
System.out.println(fromJSon:+ reverseEnumMap);


I want to make gson able to return an EnumMap object. I use the following code

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

However, I'm getting the following

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

even though I had used new TypeToken<EnumMap<Country, String>>(){}.getType() to specific I want EnumMap instead of LinkedHashMap

How can I make gson to return EnumMap?

解决方案

Even with a type token, Gson can only deserialize data into classes that have a default constructor. And EnumMap doesn't have one (it needs to be instantiated with the type of enum that its elements will match). The easiest way around this problem is to define and use an InstanceCreator:

This interface is implemented to create instances of a class that does not define a no-args constructor. If you can modify the class, you should instead add a private, or public no-args constructor. However, that is not possible for library classes, such as JDK classes, or a third-party library that you do not have source-code of. In such cases, you should define an instance creator for the class. Implementations of this interface should be registered with GsonBuilder.registerTypeAdapter(Type, Object) method before Gson will be able to use them.

Heres some example code:

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

Test code:

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

这篇关于来自Json的GSON返回LinkedHashMap而不是EnumMap的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆