Kotlin Android,从 HTTP 请求解析 Json

Posted

技术标签:

【中文标题】Kotlin Android,从 HTTP 请求解析 Json【英文标题】:Kotlin Android, Parsing Json from HTTP request 【发布时间】:2018-07-30 06:32:45 【问题描述】:

我正在尝试从 Kotlin android 文件中的 http 请求解析 json。如果我只想提取单个元素,我真的很想避免每次发出 http 请求时都必须专门使用 GSON 反序列化到一个类中。我来自 javascript 领域,将 json 解析为对象表示法是开箱即用的,所以这引起了愤怒。

这是我目前正在使用的。我正在使用 Fuel 发出 http 请求并使用 Klaxon 尝试解析它。

    Fuel.get("http://api.openweathermap.org/data/2.5/weather?q=Austin,us&appid=MYAPIKEYSUPERDUPERSECRET").responseString  request, response, result ->
            //do something with response
            result.fold( d ->
                  println("value of d")
                  println(d)
                  val parser = Parser()
                  val stringBuilder = StringBuilder(d)
                  val json: JsonObject = parser.parse(stringBuilder) as JsonObject
                  println("Weather : $json.string("weather")")
            ,  err ->
                //do something with error
            )
        

因此,当我运行上述内容时,我得到以下内容。

从我的println("value of d") 我得到

"coord":"lon":-97.74,"lat":30.27,"weather":["id":804,"main":"Clouds","description":"overcast clouds","icon":"04d"],"base":"stations","main":"temp":297.15,"pressure":1010,"humidity":69,"temp_min":296.15,"temp_max":298.15,"visibility":16093,"wind":"speed":5.7,"deg":150,"gust":11.8,"clouds":"all":90,"dt":1519082640,"sys":"type":1,"id":2558,"message":0.0053,"country":"US","sunrise":1519045581,"sunset":1519086201,"id":4671654,"name":"Austin","cod":200

细节可能并不重要,它只是从 WeatherApi 中提取的,但我可以看到它有效。此外,它似乎是一个字符串。重要的是,如果我尝试 println(d.toString()) 它会将其识别为字符串,并显示为灰色 .toString()

现在,从 Klaxon 解析中我得到以下错误:

FATAL EXCEPTION: main
 Process: com.example.patientplatypus.androidhoneytabs, PID: 32050
 java.lang.ClassCastException: com.beust.klaxon.JsonArray cannot be cast to java.lang.String
    at com.beust.klaxon.JsonObject.string(JsonObject.kt:74)
        at com.example.patientplatypus.androidhoneytabs.MainActivity$onCreate$2.invoke(MainActivity.kt:74)
        at com.example.patientplatypus.androidhoneytabs.MainActivity$onCreate$2.invoke(MainActivity.kt:39)
        at com.github.kittinunf.fuel.core.DeserializableKt$response$1.invoke(Deserializable.kt:37)
        at com.github.kittinunf.fuel.core.DeserializableKt$response$1.invoke(Unknown Source:4)
        at com.github.kittinunf.fuel.core.DeserializableKt$response$5$1.invoke(Deserializable.kt:62)
        at com.github.kittinunf.fuel.core.DeserializableKt$response$5$1.invoke(Unknown Source:0)
        at com.github.kittinunf.fuel.core.Request$callback$1.run(Request.kt:225)
        at android.os.Handler.handleCallback(Handler.java:789)
        at android.os.Handler.dispatchMessage(Handler.java:98)
        at android.os.Looper.loop(Looper.java:164)
        at android.app.ActivityThread.main(ActivityThread.java:6541)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

所以这里的错误告诉我,我正在尝试将 jsonarray 对象转换为字符串。它不能来自 d -> JsonObject。我已经看到,如果我注释掉 println("Weather : $json.string("weather")") 行,但我不确定这是否仍然意味着 val json 对象仍然被错误处理(如果它分配并且未使用,编译器是否正确评估它? )。

令人沮丧的是,根据 Klaxon 文档,这似乎是正确的用法。请参阅:https://github.com/cbeust/klaxon 及以下:

val parser: Parser = Parser()
val stringBuilder: StringBuilder = StringBuilder("\"name\":\"Cedric Beust\", \"age\":23")
val json: JsonObject = parser.parse(stringBuilder) as JsonObject
println("Name : $json.string("name"), Age : $json.int("age")")

有人知道出了什么问题吗?

快速编辑:

 result.fold( d ->
        println("value of d")
        println(d)
        val parser: Parser = Parser()
        val stringBuilder: StringBuilder = StringBuilder("\"name\":\"Cedric Beust\", \"age\":23")
        val json: JsonObject = parser.parse(stringBuilder) as JsonObject
        println("Name : $json.string("name"), Age : $json.int("age")")

正确打印塞德里克的名字。所以这似乎很好。嗯……

【问题讨论】:

【参考方案1】:

很好,我知道 Fuel。

"http://api.openweathermap.org/data/2.5/weather?q=Austin,us&appid=MYAPIKEYSUPERDUPERSECRET"
        .httpGet().responseJSON  _, _, result ->
    result.get().obj() // here you have your JSON object

注意httpGet只是Fuel.get()的另一种写法,它是String的扩展函数,重要的是我用reponseJSON而不是responseString . 您还需要在对象上使用.getString("name")。您也可以使用.getJSONObject.getJSONArray 之类的内容。

【讨论】:

谢谢!伙计,我希望这个答案比以前更明显。 @PeterWeyand 很高兴我能帮助你! “更显眼”是什么意思?

以上是关于Kotlin Android,从 HTTP 请求解析 Json的主要内容,如果未能解决你的问题,请参考以下文章

带有 Kotlin 的 Android 中的 HTTP 请求

android kotlin 中的 http 请求

在 kotlin (Android ) 中发送获取请求

【Android Kotlin】关于使用Http来获取数据的基本套路

从0到1实现一个Android路由——对Kotlin模块的支持

如何在 Kotlin 中请求 GPS 位置更新