我正在尝试解决反序列化HashMap<Integer, MyParcelablePojo>
时遇到的问题。为了找到答案,我发现了以下问题:
com.google.gson.internal.LinkedTreeMap cannot be cast to my class
Strange behavior when deserializing nested, generic classes with GSON
如果我尝试:
HashMap<Integer, MyParcelablePojo> mHashMap = new Gson().fromJson(the_json_string, HashMap.class);
...生成的
HashMap
包含LinkedTreeMap
对象而不是MyParcelablePojo
对象。因此,我试图以与上面第二个问题相同的方式使用
TypeToken
,但是它不允许我指定HashMap
的参数。如果我尝试:// XXX I am not sure if this "Type" is the correct one
// there were several "Type" classes to choose from
import java.lang.reflect.Type;
import com.google.gson.reflect.TypeToken;
Type collection_type = new TypeToken<HashMap<Integer, MyParcelablePojo>>();
... Android Studio向我显示此错误:
“ TypeToken()”已保护“ com.google.gson.reflect.TypeToken”中的访问权限
...仅是为了坚持我所看到的示例,我尝试使用
new TypeToken<HashMap<T>>
观察错误是否消失(出于好奇,我完全不愿意使用通用T
),然后它说“无法解析T”,这太奇怪了……但这与我的问题无关,我只是为了完整性而添加了它……...回到重点,所以
TypeToken
的构造函数受到保护,对吗?因此,扩展课程可能会有所帮助,对吧?但是,如果我看到了构造函数,对我来说太奇怪了。参数化类型非常奇怪地使用这种方式(至少就我目前对它们的理解而言)。 <? super T>
部分有点令人困惑(看起来它正在调用T
的父类型,但我只是没有完全理解它)。但是,对我来说更奇怪的是$Gson$Types.getRawType(type)
...我想知道这些$
用于...是什么:protected TypeToken() {
this.type = getSuperclassTypeParameter(getClass());
this.rawType = (Class<? super T>) $Gson$Types.getRawType(type);
this.hashCode = type.hashCode();
}
开门见山
我只是想避免
Gson.fromJson
方法将LinkedTreeMap
作为值而不是MyParcelablePojo
返回。链接的问题中提供的答案对我来说似乎太笼统了,所以我不知道如何将其应用于我的案例(请注意,我暂时不对笼统性感兴趣)。我什至怀疑它们是否适用于我的情况。我使用HashMap的主要动机是因为我想自己使用ID基础定义索引。我应该怎么做才能正确解决从JSON字符串反序列化的问题?
最佳答案
通过创建通常是匿名的子类来实例化TypeToken
:
Type collection_type = new TypeToken<HashMap<Integer, MyParcelablePojo>>(){}.getType();
注意我的答案中的
{}
。其原因在JavaDoc中进行了解释:/**
* Represents a generic type {@code T}. Java doesn't yet provide a way to
* represent generic types, so this class does. Forces clients to create a
* subclass of this class which enables retrieval the type information even at
* runtime.
*
* <p>For example, to create a type literal for {@code List<String>}, you can
* create an empty anonymous inner class:
*
* <p>
* {@code TypeToken<List<String>> list = new TypeToken<List<String>>() {};}
*
* <p>This syntax cannot be used to create type literals that have wildcard
* parameters, such as {@code Class<?>} or {@code List<? extends CharSequence>}.
*
* @author Bob Lee
* @author Sven Mawson
* @author Jesse Wilson
*/