You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何第二次遍历JSONObject的keys时循环未执行?

问题原因与解决方案

核心问题

你遇到的循环不执行的原因是:JSONObject.keys()返回的Iterator是一次性的。第一次遍历表头时,已经把迭代器里的所有元素取完,迭代器内部指针走到末尾。第二次复用这个迭代器时,hasNext()会直接返回false,所以循环不会执行——这是迭代器的正常行为,不会触发报错。

修复方案

把迭代器转换成可重复遍历的集合(比如List<String>),这样每次遍历都能从头开始获取元素。修改drawTable方法中获取keys的逻辑即可:

修改后的代码

override fun drawTable(jsonArrayData: JSONArray) {
    // ------ Draw the table -----
    // Draw the keys first
    val headerRow = TableRow(requireActivity())
    Log.d("jsonArray", jsonArrayData[0].toString())
    val firstRecord = jsonArrayData[0] as JSONObject
    // 将迭代器转为List,支持重复遍历
    val keys = firstRecord.keys().asSequence().toList()

    for (key in keys) {
        val textView = TextView(requireActivity())
        textView.text = key
        headerRow.addView(textView)
    }
    binding.table.addView(headerRow)

    // Draw the data second
    for (i in 0 until jsonArrayData.length()) {
        val record = jsonArrayData[i] as JSONObject
        Log.d("Record", record.toString())
        val tableRow = TableRow(requireActivity())
        Log.d("Table Row", "Table Row created")
        Log.d("Keys", keys.toString())

        // 现在可以正常遍历keys生成单元格
        for (key in keys) {
            Log.d("key", key)
            val textView = TextView(requireActivity())
            // 优化:避免强转String崩溃,转为安全的toString处理
            val cellText = record[key]?.toString() ?: ""
            textView.text = cellText
            tableRow.addView(textView)
        }
        binding.table.addView(tableRow)
    }
}

额外说明

  1. 迭代器特性:Java/Kotlin中的Iterator是单向、一次性的遍历工具,遍历完成后无法重置或重新遍历,必须重新获取迭代器或者转换为可重复访问的集合。
  2. 类型安全优化:原代码中record[key] as String如果遇到非String类型的JSON值(比如数字、布尔值)会抛出ClassCastException,改用record[key]?.toString() ?: ""可以避免崩溃,同时兼容不同数据类型。

内容的提问来源于stack exchange,提问作者David Frick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 01:54:59