Kotlin : JSONArray를 통해 반복


79

Kotlin과 Realm을 사용하여 Android 앱을 작성하고 있습니다. JSONArray가 있고 Realm 데이터베이스 클래스에로드하기 위해이 배열의 JSONObject를 반복하고 싶습니다.

영역 클래스 :

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 라이브러리를 사용하고 있습니까?
mfulton26

나는 org.json.JSONArrayorg.json.JSONObject.
Ambran

답변:


152

불행히도 JsonArray반복자를 노출하지 않습니다. 따라서 인덱스 범위를 사용하여 반복해야합니다.

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

    // Your code here
}

43
좋네요은 다음과 같습니다에 (내가 0 persons.length ()까지)
포인터 널

8
for(i in 0 until persons.length()끔찍한 일회성 문제를 피하는 데 도움이되는 것처럼 보이므로 확실히 더 좋습니다. 하지만 반복자가 노출되지 않는 이유는 무엇입니까? 이것은 기본적으로 미친 것처럼 보입니다 ... 전적으로 여러 객체에 초점을 맞춘 핵심 객체 유형입니다. 반복은 자연스럽지 않습니까 ???
Mike Williamson

많은 도움이됩니다. 고마워요.
marcode_ely

1
나는 범위 예외 나왔다
famfamfam

41

일부 클래스가 iterator메서드를 노출하지 않더라도 for확장 함수를 제공하여 문으로 반복 할 수 있습니다 iterator.

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

이제 JSONArrayin for문 을 사용할 때이 확장이 호출되어 반복자를 가져옵니다. 인덱스 범위를 만들고 각 인덱스를이 인덱스에 해당하는 항목에 매핑합니다.

JSONObject배열에는 객체뿐만 아니라 기본 요소 및 기타 배열도 포함될 수 있으므로 캐스트 가 필요하다고 생각합니다 . 그리고 게으른 방식으로 작업 asSequence을 실행하라는 호출이 여기에 map있습니다.

일반적인 방법 ( 모든 배열 항목이 동일한 유형 이라고 가정 )

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

3
감사합니다 Ilya. Kotlin 초보자로서 얻을 수있는 모든 의견에 감사드립니다.
Ambran

1
Kotlin의 특정 기능을 더 많이 활용하므로이 솔루션을 선호합니다
Nick Felker 2017 년

2
물론 항상 JSONObject 배열이있는 것은 아닙니다. 시도해 볼 수 있습니다. operator fun <T> JSONArray.iterator(): Iterator<T> = (0 until length()).asSequence().map { get(it) as T }.iterator()이제는 물론 "확인되지 않은 캐스트"가 있습니다.
androidguy jul.

1
@Sevastyan 0 until length()은 배열이 비어 있으면 빈 범위를 생성하므로 빈 범위의 get요소에 대해 0 번 호출됩니다 (즉, 전혀 호출되지 않음).
Ilya

2
당신은 신속하게 확인할 수 있습니다 @Sevastyan 0 until 0와 평가 try.kotlinlang.org
일리아

3

어때

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

?


jsonArray.getJSONObject(r)jsonArray.getJSONObject(i)내가 뭔가를 오해 해야 합니까?
Ambran

그래, 당신 말이 맞아, 그것은해야 i하지 r. 고정 코드 예.
Sharif

1
로 정제 할 수(0 until (jsonArray.length()))
Jimit 파텔

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

1
좀 더 설명해 주시겠습니까?
Dieter Meemken 19

2
이 코드가 문제를 해결할 수 있지만 문제를 해결하는 방법과 이유에 대한 설명포함 하여 게시물의 품질을 향상시키는 데 실제로 도움이되며 아마도 더 많은 찬성 투표를 받게됩니다. 지금 질문하는 사람뿐만 아니라 미래에 독자를 위해 질문에 답하고 있다는 것을 기억하십시오. 제발 편집 설명을 추가하고, 제한 및 가정이 적용 무엇의 표시를 제공하는 답변을.
Dave 19

0

가장 짧은 방법은 다음과 같습니다.

(0 until persons.length()).forEach {
    val item = persons.getJSONObject(it)

기본적으로 0에서 jsonarray 길이까지의 범위에서 한 번에 하나의 숫자를 취하고 현재 객체를 검색하는 인덱스로 사용합니다.


답변을 주셔서 감사합니다. 코드에 대한 설명을 포함하도록에 대한 답변을 친절하게 편집 하시겠습니까? 이는 미래의 독자들, 특히 언어에 익숙하지 않고 개념을 이해하기 위해 고군분투하는 커뮤니티 구성원을 더 잘 이해하는 데 도움이 될 것입니다.
Jeremy Caney
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.