简体   繁体   中英

Kotlin Android, Parsing Json from HTTP request

I'm trying to parse json from an http request in a Kotlin Android file. I'd really like to avoid having to specifically use GSON to deserialize into a class every time I make an http request if I just want to pull a single element. I come from javascript land where parsing json into object notation comes right out of the box, so this has caused irritation.

Here is what I am working with currently. I'm using Fuel to make the http request and Klaxon to try and parse it.

    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
            })
        }

So when I run the above I get the following.

From my println("value of d") I get

{"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}

The specifics are probably not important, it's just a pull from WeatherApi, but I can see that it works. Also, that it appears to be a string. Importantly if I try and println(d.toString()) it recognizes it as a string, and greys out .toString()

Now, from the Klaxon parsing I get the following error:

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)

So the error here is telling me that somewhere I am trying to cast a jsonarray object to a string. It can't be from d -> JsonObject. I have seen that if I comment out the line println("Weather : ${json.string("weather")}") , but I'm not sure if that still means that the val json object is still being mishandled (if it assigns and isn't used does the compiler properly evaluate it?).

What's frustrating is that this appears to be proper usage according to the Klaxon documentation. See: https://github.com/cbeust/klaxon and below:

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")}")

Does anyone have any ideas what is going wrong?

Quick Edit:

 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")}")

Does correctly print Cedric's name. So that seems fine. Hmm....

Neat, that I know 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
}

Note , that httpGet is just another way of writing Fuel.get() , it is a String extension function and the important part is that I used reponseJSON instead of responseString . Also you will need to use .getString("name") on the object. You can also use something like .getJSONObject or .getJSONArray .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM