英文:
Gson error "Not enough information to infer type variable T" when passing the TypeToken
问题
我想反序列化我从不同活动返回的地图列表。以下是我的代码:
val listType = object : TypeToken<List<Map<String, Any>>>() {}.type
val stepsList = Gson().fromJson(resultStr, listType)
在这里的fromJson()
显示错误 "没有足够的信息来推断类型变量 T。"
我不明白当我明确为我的对象指定了TypeToken时,这是如何可能的。我尝试了几种不同的方法来获取列表类型(包括内联函数),但它们都导致相同的错误。如何使它工作?
英文:
I want to deserialize the list of maps that I return from a different activity. Here is my code:
val listType = object : TypeToken<List<Map<String, Any>>>() {}.type
val stepsList = Gson().fromJson(resultStr, listType)
fromJson()
here shows the error "Not enough information to infer type variable T."
I don't understand how this is possible when I literally specify the TypeToken for my object. I tried a couple different methods of getting the list type (including the inline functions) but they all result in the same error. How can I make it work?
答案1
得分: 1
你需要指定 fromJson
调用的类型:
Gson().fromJson<List<Map<String, Any>>>(resultStr, listType)
这应该会解决这个错误。
英文:
You have to specify the type of the fromJson
call:
Gson().fromJson<List<Map<String, Any>>>(resultStr, listType)
This should fix the error.
答案2
得分: 0
Gson有一些Gson.fromJson(..., Type): T
方法,其中的T
在任何情况下都不受传递给fromJson
的参数的限制。因此,编译器无法确定stepsList
的类型,因为它可以是任何类型,你必须自己选择。通常,当编译器可以推断出类型时,你不必显式指定类型。
然而,这个错误实际上突显了Gson API的一个缺陷:这些fromJson(..., Type)
方法不是类型安全的,作为用户,你甚至在编译时都不会注意到,只有在运行时遇到ClassCastException
时才会注意到。例如,以下代码编译没有问题,但是在运行时会出错:
val listType = object : TypeToken<List<MyClass>>() {}.type
// 在这里指定了错误的类型;在编译时没有警告
val stepsList: List<DefinitelyNotMyClass> = Gson().fromJson("[{}]", listType)
// 在运行时失败,出现ClassCastException
val obj: DefinitelyNotMyClass = stepsList[0]
如果你使用的是Gson 2.10或更新版本,应该优先使用fromJson(..., TypeToken<T>): T
方法。在这些方法中,结果类型T
受到类型令牌参数的约束,因此这些方法是类型安全的。因此,你也不再需要第二次指定类型,因为编译器现在可以推断出类型。要使用这些方法,只需省略TypeToken
的.type
调用:
val listType = object : TypeToken<List<Map<String, Any>>>() {}
val stepsList = Gson().fromJson(resultStr, listType)
英文:
Gson has a few Gson.fromJson(..., Type): T
methods where the T
is not constrained in any way by the arguments you pass to fromJson
. Therefore the compiler cannot determine the type of stepsList
because it can be anything, and you can (and have to) choose it. Often you don't have to explicitly specify the type when the compiler can infer it.
However, this error actually highlights a flaw with the API of Gson: These fromJson(..., Type)
methods are not type safe, and you as user would not even notice it at compile time, but would only notice it at runtime when you encounter a ClassCastException
. For example, the following compiles just fine, but it is wrong and fails at runtime:
val listType = object : TypeToken<List<MyClass>>() {}.type
// Specifies the wrong type here; no warning at compile time
val stepsList: List<DefinitelyNotMyClass> = Gson().fromJson("[{}]", listType)
// Fails with ClassCastException at runtime
val obj: DefinitelyNotMyClass = stepsList[0]
If you are using Gson 2.10 or newer you should prefer the fromJson(..., TypeToken<T>): T
methods. Here the result type T
is constrained by the type token parameter, so these methods are type safe. You therefore also don't have to specify the type a second time anymore because the compiler can now infer the type. To use these methods, simply omit the .type
call for the TypeToken
:
val listType = object : TypeToken<List<Map<String, Any>>>() {}
val stepsList = Gson().fromJson(resultStr, listType)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论