【问题标题】:How does Gson.fromJson method succeeded to parse a Json string although TypeToken isn't suit to parsed String?尽管 TypeToken 不适合解析的字符串,但 Gson.fromJson 方法如何成功解析 Json 字符串?
【发布时间】:2020-11-16 16:15:05
【问题描述】:

我有一段代码我不明白为什么它没有抛出运行时异常。 这是一个 Json 字符串,我正在尝试将其转换为 Map, 但是 一些键 来自 Int 类型而不是 String 。 代码:

    val json = """{1: "Kotlin Tutorial", "2": "bezkoder", "3" : ["Kotlin","Basic"]}"""
    val gson = Gson()

    var tutorialMap: Map<Int, Any> = gson.fromJson(json, object : TypeToken<Map<Int, Any>>() {}.type)
    tutorialMap.forEach { Log.e("dadffas",it.toString()) }

如您所见,keys: 1,3 来自 Int 类型。这里发生了什么?某种拳击? 此外,如果我将 TypeToken 声明为 Map 代码仍在编译中?又是一种拳击(在后台运行 String.toInt 方法)?

【问题讨论】:

  • 1) JSON 既不支持 int 也不支持 numeric 键:有效的 JSON 文档只能包含字符串键、句点。 2) Gson 对格式错误的 JSON 文档非常宽容,并允许读取数字键,就好像它们是字符串一样。 github.com/google/gson/blob/…
  • @fluffy,我进入链接但不明白那里发生了什么 :( 另外我写道:* 此外,如果我将 TypeToken 声明为 Map 代码仍然正在编译?又是一种拳击(在 String.toInt 方法正在运行的场景后面)?* 是真的吗?
  • 它被编译是因为你使用的fromJson方法重载接受Type的实例,而不是TypeToken,它可以从以下位置推断结果类型:两者left 类型和 right 类型在这种情况下是不相关的。这不是一种“拳击”(我相信幕后没有像 String.toInt 这样的东西,因为对象属性名称总是被读取为字符串,即使它们看起来像数字)。
  • 因此,it.key.javaClass始终返回java.lang.String。它在运行时不会失败的原因是您没有将密钥取消引用为Int,这会在运行时引发类转换异常。
  • 我已编辑帖子(更改 tutorialMap 变量类型)。您说 it.key.javaClass 将始终返回 java.lang.String 但以下分配有效: var vv: Class = it.key.javaClass 和 var vv: Class = it.key.javaClass 无效

标签: java android json kotlin gson


【解决方案1】:

Gson 的方法是,来自 Java/Kotlin 端并尝试将 Json 值强制转换为 Java 端预期的类型。 因此,由于您的地图键的类型是整数,它会尝试将其从 Json 获取的内容强制转换为整数。

您需要注意,您的整个 Json 最初只是 Gson 的一个字符串。它被标记化但仍然是一堆字符串,直到最后 Gson 看到你想要某个字符串作为整数。它非常聪明,可以将2"2" 转换为整数。

如果你的 json 有一个像 "foo" 这样的键,你会得到一个异常。

P.S:如果您真的感兴趣,可以使用调试器并单步执行 fromJson() 方法,看看它是如何完成的。

【讨论】:

  • 我真的很想跟着,但是堆栈太长了,函数调用另一个函数调用另一个函数..所以我真的很困惑..我觉得自己是世界上最糟糕的程序员跨度>
  • 别担心。通常不需要进入库代码。此外,您对“为什么代码有效”的兴趣清楚地表明,您不是一个糟糕的程序员。
猜你喜欢
  • 2012-10-25
  • 2016-09-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-05-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多