【问题标题】:Why does Moshi parse integers, longs as Double?为什么 Moshi 解析整数,长为 Double?
【发布时间】:2021-09-26 04:42:42
【问题描述】:

我正在尝试使用 Moshi + kotlin 解析一个设计不太好的 api 的 json。由于某些原因,它会将 71 等数字解析为 Double。

第 3 方 api 有一个对象列表,可能如下所示: {"foo":[[1234567000,12]]} // long, int 要么 {"foo":[[1234567000,"string",0,2]]} // long, string, int, int

由于 3rd 方 api,我有以下 kotlin 类:

@JsonClass(generateAdapter = true)
class D {
    var foo: List<Any> // I use Any because it can be either String or Int or Long
}

在我的代码中,我做了类似的事情:

val moshi = Moshi.Builder().build()
val adapter = moshi.adapter(D::class.java)
var D d = adapter.fromJson("{\"foo\":[[1234567000,\"string\",0,2]]}")
var index = d.foo[2]
var value : Long = 0
// here I get an error: ClassCastException: java.lang.Double cannot be cast to java.lang.Long
value = d.foo[index]

但由于某种原因,Moshi 将 json 字符串中的整数转换为 Doubles 而不是 Int 或 Long。我该如何解决?

【问题讨论】:

  • 你能转换一下吗? kotlinlang.org/api/latest/jvm/stdlib/kotlin/-double/…value = d.foo[index].toLong()
  • 我没有尝试过,但由于我的情况下的 long 是时间戳,我不想冒险获得一个四舍五入的值。
  • 我希望一个 long 值被视为 double 被强制转换回 long 不会有舍入错误。 IE。 123456789 将是 123456789.0,它将“四舍五入”回到 123456789。您应该能够通过单元测试来证明这一点。

标签: kotlin moshi


【解决方案1】:

我不确定这是否是最简单的方法,但它有效:

class AnyAdapter {
    @FromJson fun fromJson(str: String): Any {
        var any: Any
        try {
            any = Integer.parseInt(str)
        } catch (e: NumberFormatException) {
            try {
                any = java.lang.Long.parseLong(str)
            } catch (e: NumberFormatException) {
                try {
                    any = java.lang.Double.parseDouble(str)
                } catch (e: NumberFormatException) {
                    any = str
                }
            }
        }
        return any
    }
}
val moshi = Moshi.Builder()
        .add(AnyAdapter())
        .build()
val adapter = moshi.adapter(D::class.java)
var D d = adapter.fromJson("{\"foo\":[[1234567000,\"string\",0,2.0]]}")

var l : Long = d.foo[0] as Long
var s : String = d.foo[1] as String
var i : Int = d.foo[2] as Int
var dd : Double = d.foo[3] as Double

【讨论】:

  • 如果您收到一个实际上看起来像数字的字符串值会发生什么?
  • 是的,这是对的,对于非常一般的情况,但它适用于我正在使用的 api,因为那里的字符串是像“MEASURED”、“GUESSED”这样的状态。您也可以争辩说数字 1 可能需要是 Long 而不是 Int,但这很好,因为我稍后会转换它。其实我会更新我答案的最后 4 行...
【解决方案2】:

JSON数字类型不区分整数和浮点数

任何 JSON 解析库背后的基本思想是将 JSON 解析为特定类型,如果该类型具有整数类型的属性,则解析库将尝试将 JSON 数字类型转换为整数,但您将 json 解析为 Any,这实际上告诉moshi 来猜测 Object 的类型。

由于 JSON 不区分整数和浮点字段,所以当解析为 Any 时,moshi 默认为数字字段使用 Float/Double。

这里的问题在于 API,它不应该为同一个查询返回不同的类型值。至少应该说明数据的类型。 如果您收到一个实际上看起来像数字的字符串值会怎样?

【讨论】:

  • 嗯,好的,我明白了,虽然我认为 Moshi 可能更“聪明”或“勇敢”一点。例如,我不会将其中没有点的数字转换为 Double。
猜你喜欢
  • 1970-01-01
  • 2018-01-25
  • 1970-01-01
  • 2012-09-19
  • 1970-01-01
  • 1970-01-01
  • 2021-04-10
  • 1970-01-01
  • 2011-07-13
相关资源
最近更新 更多