Gson错误:”无法推断类型变量T的足够信息”,当传递TypeToken时

huangapple go评论64阅读模式
英文:

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&lt;List&lt;Map&lt;String, Any&gt;&gt;&gt;() {}.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&lt;List&lt;Map&lt;String, Any&gt;&gt;&gt;(resultStr, listType)

这应该会解决这个错误。

英文:

You have to specify the type of the fromJson call:

Gson().fromJson&lt;List&lt;Map&lt;String, Any&gt;&gt;&gt;(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&lt;List&lt;MyClass&gt;&gt;() {}.type
// 在这里指定了错误的类型;在编译时没有警告
val stepsList: List&lt;DefinitelyNotMyClass&gt; = Gson().fromJson(&quot;[{}]&quot;,  listType)
// 在运行时失败,出现ClassCastException
val obj: DefinitelyNotMyClass = stepsList[0]

如果你使用的是Gson 2.10或更新版本,应该优先使用fromJson(..., TypeToken&lt;T&gt;): T方法。在这些方法中,结果类型T受到类型令牌参数的约束,因此这些方法是类型安全的。因此,你也不再需要第二次指定类型,因为编译器现在可以推断出类型。要使用这些方法,只需省略TypeToken.type调用:

val listType = object : TypeToken&lt;List&lt;Map&lt;String, Any&gt;&gt;&gt;() {}
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&lt;List&lt;MyClass&gt;&gt;() {}.type
// Specifies the wrong type here; no warning at compile time
val stepsList: List&lt;DefinitelyNotMyClass&gt; = Gson().fromJson(&quot;[{}]&quot;,  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&lt;T&gt;): 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&lt;List&lt;Map&lt;String, Any&gt;&gt;&gt;() {}
val stepsList = Gson().fromJson(resultStr, listType)

huangapple
  • 本文由 发表于 2023年6月8日 01:02:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76425592.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定