如何从 API 中解析不规则的 JSON 字符串

How to parse an irregular JSON string from an API

你好,我是 Android Studio Kotlin 的新手,我被困在这个问题上:我有一个由 OpenWeatherMap 返回的 JSON 字符串 API.A 类似的问题出现在过去 ,但现在是 Java。

This is a typical string:

 {
    "coord": {
        "lon": -2.93,
        "lat": 43.26
    },
    "weather": [{
        "id": 801,
        "main": "Clouds",
        "description": "few clouds",
        "icon": "02n"
    }],
    "base": "stations",
    "main": {
        "temp": 60.69,
        "feels_like": 62.33,
        "temp_min": 59,
        "temp_max": 63,
        "pressure": 1023,
        "humidity": 100
    },
    "visibility": 10000,
    "wind": {
        "speed": 3.36,
        "deg": 120
    },
    "clouds": {
        "all": 20
    },
    "dt": 1602195029,
    "sys": {
        "type": 1,
        "id": 6395,
        "country": "ES",
        "sunrise": 1602224311,
        "sunset": 1602265138
    },
    "timezone": 7200,
    "id": 3128026,
    "name": "Bilbao",
    "cod": 200
}

这是我的代码:

package com.example.downloadtest

import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import org.jetbrains.anko.doAsync
import org.jetbrains.anko.uiThread
import org.json.JSONObject
import java.net.URL
import java.util.concurrent.Executors

val executor = Executors.newScheduledThreadPool(5)



class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        doAsync(executorService = executor) {
            //val result = URL("https://httpbin.org/get").readText()
            val result = URL("https://api.openweathermap.org/data/2.5/weather?q=Bilbao,spain&units=imperial&APPID=-------------").readText()
            val textView = findViewById(R.id.txtView) as TextView
            uiThread {
                //textView.setText(result)
                println(result)
                //toast(result)
                val data = StringBuilder()
                val jsonObject = JSONObject(result)
                val jsonArray = jsonObject.optJSONArray("weather")
                println(jsonArray)
                for (i in 0 until jsonArray.length()){
                    val jsonObject = jsonArray.getJSONObject(i)
                    val main = jsonObject.optString("main").toString()
                    val desc = jsonObject.optString("description").toString()
                    val icon = jsonObject.optString("icon").toString()
                    data.append("Bilbao Weather: \n").append(main).append(" : ").append(desc).append(" : ").append(icon)
                    textView.text = data.toString()
                }
            }
        }

    }

}

如您所见,我可以解析字符串的一部分,但无法解析其他任何内容。如果我想解析“国家”或“名称”,我该怎么做?

在此先感谢您的帮助。

雷.

您的 json 由嵌套对象组成。如果不访问对象本身,就无法访​​问对象的内部。

如果你想访问description参数,你首先需要使weather成为一个对象。与 country 相同,您需要从 sys.

创建一个对象

你会这样做:

val sys: JSONObject? = jsonObject.optJSONObject("sys") //this can be null (I don't know how consistent is that model)
val country = sys?.optString("country") ?: "" //if sys is null, default to empty string

至于名字,就是初始对象的一个​​属性,所以这样访问起来很方便:

val name = jsonObject.optString("name")

需要考虑的一件事是:你为什么在 String 上做 .toString()

函数 optString("fieldName", "fallback") 将始终 return 一个 String,如果您提供后备,它将使用它,否则它将 return 一个空的 String

你还应该考虑(在长 运行 上)如果你想创建一个模型 json 的对象,并用 jackson 或任何其他库映射它,那么你会像访问任何其他 java/kotlin 参数一样访问它们。