1. 简介

本文将介绍如何在 Kotlin 中遍历 JSONArray 对象。

我们会先尝试使用传统的 for 循环方式,然后通过扩展函数(extension function)来优化代码,让遍历更简洁、更符合 Kotlin 的惯用写法。这种技巧不仅能提升可读性,还能避免重复“样板代码”——这可是实际开发中常见的踩坑点。

2. 遍历 JSONArray

⚠️ 关键点:JSONArray 类并未实现 Iterable 接口,因此无法直接用于 Kotlin 的 for-each 循环(即 for (item in collection) 这种语法)。

这意味着你不能这样写:

// ❌ 编译报错!JSONArray 没有 iterator()
for (book in booksJSONArray) {
    println(book)
}

那怎么办?我们来看几种替代方案。

2.1 使用 for 循环手动遍历

最直接的方式是通过索引进行遍历:

val booksJSONArray = JSONArray(BOOKS_STRING)
for (i in 0 until booksJSONArray.length()) {
    val book = booksJSONArray.getJSONObject(i)
    println("${book.get("book_name")} by ${book.get("author")}")
}

✅ 输出示例:

The Great Gatsby by F. Scott Fitzgerald
To Kill a Mockingbird by Harper Lee

你也可以改用 forEach 结合区间表达式,使代码更具函数式风格:

val booksJSONArray = JSONArray(BOOKS_STRING)
(0 until booksJSONArray.length()).forEach {
    val book = booksJSONArray.getJSONObject(it)
    println("${book.get("book_name")} by ${book.get("author")}")
}

虽然这种方式比原始 for 循环稍显现代,但仍然不够直观,尤其是当你频繁处理 JSON 数据时,容易写出大量重复逻辑。

2.2 添加便捷的扩展函数

Kotlin 的一大优势就是支持扩展函数,我们可以借此“修补” JSONArray 的短板,让它支持标准的 for-in 遍历。

目标效果如下:

// ✅ 现在可以这么写了!
for (book in booksJSONArray) {
    println("${(book as JSONObject).get("book_name")} by ${(book as JSONObject).get("author")}")
}

要实现这一点,只需定义一个操作符扩展函数 iterator()

operator fun <T> JSONArray.iterator(): Iterator<T> =
    (0 until this.length()).asSequence().map { this.get(it) as T }.iterator()

📌 解析一下这段代码:

  • operator 关键字:让该函数成为合法的迭代器操作符,从而支持 for-in 语法。
  • 泛型 <T>:允许返回任意类型(实际使用中通常是 JSONObjectString)。
  • 利用 (0 until length()) 生成索引序列,再通过 map 转换为实际元素。
  • 最终调用 .iterator() 返回标准迭代器。

一旦这个扩展函数被导入作用域,所有 JSONArray 实例都将“获得”迭代能力。

🎯 使用建议:

  • 将此扩展函数放在工具类或顶层函数文件中(如 JsonExtensions.kt),便于复用。
  • 注意类型转换安全问题,确保你知道 JSONArray 中存储的是 JSONObject 还是基本类型。

3. 总结

  • JSONArray 原生不支持 Iterable,无法直接用于 for-in 循环。
  • ✅ 可通过索引循环(forforEach)完成遍历,适合简单场景。
  • ✅ 更优雅的做法是使用 operator fun JSONArray.iterator() 扩展函数,使其无缝集成进 Kotlin 的集合遍历体系。
  • 💡 此技巧适用于任何未实现 Iterable 但可通过索引访问的容器类,属于典型的“Kotlin 扩展思维”。

所有示例代码已托管至 GitHub:https://github.com/Baeldung/kotlin-tutorials/tree/master/kotlin-json

示例中的 BOOKS_STRING 可 mock 如下:

const val BOOKS_STRING = """
[
  {"book_name": "The Great Gatsby", "author": "F. Scott Fitzgerald"},
  {"book_name": "To Kill a Mockingbird", "author": "Harper Lee"}
]
"""

原始标题:Iterate Through a JSONArray in Kotlin