为什么 Moshi 将整数解析为 Double?

Why does Moshi parse integers, longs as Double?

我正在尝试使用 Moshi + kotlin 解析设计不是很好的 api 的 json。由于某些原因,它将 71 之类的数字解析为 Double。

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

因为第 3 方 api 我有以下 kotlin class:

@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 字符串中的整数转换为 Double,而不是 Int 或 Long。我该如何解决?

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

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

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

任何JSON解析库背后的基本思想是将JSON解析为某种类型,如果该类型具有整数类型的属性,那么解析库将尝试转换JSON数字类型为整数,但您正在将 json 解析为 Any,这实际上告诉 moshi 猜测对象的类型。

因为 JSON 不区分整数和浮点字段 moshi 在解析为 Any 时默认为数字字段 Float/Double。

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