Android Studio Kotlin中解析OpenWeatherMap API JSON字段问题
解决Kotlin中解析OpenWeatherMap JSON额外字段的问题
嘿,作为Android Studio Kotlin新手,你已经搞定了weather数组的解析,距离拿到所有需要的字段只差几步啦!下面我会一步步教你如何获取country、name这些字段,还有其他常用的嵌套数据:
1. 解析顶层字段(比如城市名name)
像name、cod、visibility这类直接在JSON最外层的字段,你可以直接从最开始创建的jsonObject中获取:
val cityName = jsonObject.optString("name") // 拿到Bilbao val visibility = jsonObject.optInt("visibility") // 拿到10000
2. 解析嵌套对象中的字段(比如sys里的country)
对于sys、main这种嵌套的JSON对象,你需要先获取对应的子JSONObject,再从中提取字段。这里要注意空安全,用?.安全调用避免空指针:
// 获取sys对象里的国家码 val sysObj = jsonObject.optJSONObject("sys") val countryCode = sysObj?.optString("country") // 拿到ES // 获取main对象里的温度等数据 val mainObj = jsonObject.optJSONObject("main") val temp = mainObj?.optDouble("temp") // 拿到60.69 val humidity = mainObj?.optInt("humidity") // 拿到100
3. 修改你的完整代码
我帮你调整了原代码,修复了变量名冲突(循环里的jsonObject改成了weatherObj,避免覆盖外层对象),并加入了所有你需要的字段解析:
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) val textView = findViewById(R.id.txtView) as TextView // 把TextView初始化移到外面,避免重复查找 doAsync(executorService = executor) { val result = URL("https://api.openweathermap.org/data/2.5/weather?q=Bilbao,spain&units=imperial&APPID=-------------").readText() uiThread { val data = StringBuilder() val jsonObject = JSONObject(result) // 解析顶层字段:城市名 val cityName = jsonObject.optString("name") data.append("城市: ").append(cityName).append("\n") // 解析sys对象里的国家码 val sysObj = jsonObject.optJSONObject("sys") val countryCode = sysObj?.optString("country") ?: "未知" // 用?:给默认值 data.append("国家: ").append(countryCode).append("\n") // 解析weather数组 val jsonArray = jsonObject.optJSONArray("weather") if (jsonArray != null && jsonArray.length() > 0) { for (i in 0 until jsonArray.length()){ val weatherObj = jsonArray.getJSONObject(i) // 重命名变量避免冲突 val main = weatherObj.optString("main") val desc = weatherObj.optString("description") val icon = weatherObj.optString("icon") data.append("天气状况: ").append(main).append(" - ").append(desc).append(" (图标: ").append(icon).append(")\n") } } // 解析main对象里的温度数据 val mainObj = jsonObject.optJSONObject("main") val temp = mainObj?.optDouble("temp") ?: 0.0 val humidity = mainObj?.optInt("humidity") ?: 0 data.append("当前温度: ").append(temp).append("°F\n") data.append("湿度: ").append(humidity).append("%") textView.text = data.toString() } } } }
几个小提示
- 变量名冲突:原代码中循环里的
jsonObject会覆盖外层的jsonObject,这会导致后续无法访问顶层字段,所以我改成了weatherObj - 空安全处理:用
?.安全调用和?:Elvis操作符给字段设置默认值,避免API返回null时崩溃 - UI元素初始化:把
TextView的初始化移到doAsync外面,避免在后台线程和UI线程重复查找控件
内容的提问来源于stack exchange,提问作者Ray
相关产品推荐
相关产品推荐

