Kotlin:遍历JSONArray


78

我正在使用Kotlin和Realm编写一个Android应用程序。我有一个JSONArray,并且我想遍历此数组中的JSONObject以便将它们加载到Realm数据库类中:

领域类:

import io.realm.RealmObject
import io.realm.annotations.PrimaryKey
import io.realm.annotations.Required

open class Person(

        @PrimaryKey open var id: Long = 0,

        @Required
        open var name: String = ""

) : RealmObject() {

}

JSONArray:

{
    "persons":[
        {
           "id":0,
           "name":"Biatrix"
        },
        {
           "id":1,
           "name":"Bill"
        },
        {
           "id":2,
           "name":"Oren"
        },
        {
           "id":3,
           "name":"Budd"
        }
    ]
}

我尝试过如下迭代:

for (item : JSONObject in persons) {

}

...但是我得到一个for-loop range must have an iterator() method错误。


您正在使用哪个JSON库?
mfulton16年

我使用org.json.JSONArrayorg.json.JSONObject
Ambran

Answers:


149

不幸的是,JsonArray没有公开迭代器。因此,您将不得不使用索引范围遍历它:

for (i in 0 until persons.length()) {
    val item = persons.getJSONObject(i)

    // Your code here
}

43
更好的是:for(i in 0直到person.length())
指针为空,

7
for(i in 0 until persons.length()绝对更好,因为它似乎有助于避免可怕的“一对一”问题。但是为什么不公开迭代器呢?默认情况下,这似乎很疯狂……这是一种核心对象类型,它完全专注于多个对象。遍历似乎很自然,对吧???
迈克·威廉姆森

它对我有很大帮助。谢谢你
marcode_ely

我超出范围例外
famfamfam,

41

即使某些类没有公开iterator方法,您仍然可以for通过提供扩展功能来使用语句对其进行迭代iterator

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

现在,当您使用JSONArrayinfor语句时,将调用此扩展名以获取迭代器。它创建一系列索引,并将每个索引映射到与此索引对应的项目。

我认为强制转换JSONObject为必需,因为数组不仅可以包含对象,而且还可以包含基元和其他数组。asSequence此处的调用map以惰性方式执行操作。

通用方式(假设所有数组条目均为同一类型)

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

3
谢谢伊利亚。作为Kotlin的新手,我很感激我能获得的所有输入。
Ambran

1
我更喜欢这种解决方案,因为它可以充分利用Kotlin的特定功能
Nick Felker

2
当然,您不一定总是拥有JSONObject数组。您可能要尝试:operator fun <T> JSONArray.iterator(): Iterator<T> = (0 until length()).asSequence().map { get(it) as T }.iterator()现在,它当然具有“未经检查的演员表”。
androidguy

1
0 until length()如果数组为空,@ Sevastyan将产生一个空范围,因此get在该空范围的元素上将被调用0次(即根本不会被调用)。
伊利亚

2
@Sevastyan您可以0 until 0使用try.kotlinlang.org
Ilya

3

怎么样

(0..(jsonArray.length()-1)).forEach { i ->
    var item = jsonArray.getJSONObject(i)
}


jsonArray.getJSONObject(r)应该jsonArray.getJSONObject(i)还是我误会了什么?
安布兰'18

是的,您是正确的,应该i不正确r。固定代码示例。
谢里夫

1
可以细化为(0 until (jsonArray.length()))
Jimit Patel

1
for (i in 0 until jsonArray.length()){
    //do your stuff
    }

1
你能解释更多吗?
Dieter Meemken

2
尽管这段代码可以解决问题,但包括解释如何以及为什么解决该问题的说明,确实可以帮助提高您的帖子质量,并可能导致更多的投票。请记住,您将来会为读者回答问题,而不仅仅是现在问的人。请编辑您的答案以添加解释,并指出适用的限制和假设。
戴夫
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.