Ітерація масиву JSON в Android / Java


148

Я будую додаток для Android, якому потрібно завантажувати та синхронізуватись із онлайн-базою даних, я надсилаю свій запит із програми на сторінку php, яка повертає відповідні рядки з бази даних у форматі JSON.

може хто-небудь, будь ласка, скажіть мені найкращий спосіб ітерації через масив JSON?

Я отримую масив об’єктів:

[{json object},{json object},{json object}]

Який найпростіший фрагмент коду, який я міг би використати для доступу до JSONObjects в масиві?

EDIT: тепер, коли я думаю про це, метод, який я використовував для повторення циклу, був:

for (String row: json){
     id = row.getInt("id");
     name = row.getString("name");
     password = row.getString("password");
}

Тож я здогадуюсь, що я якось зміг перетворити повернутого Джсона в масив, який можна повторити. Будь-які ідеї, як я міг цього досягти?

Прошу вибачення за свою розпливчастість, але я працював на прикладі, який я знайшов в Інтернеті, і з тих пір не зміг його знайти.


1
перевірити по наступним посиланням: androidbeasts.wordpress.com/2015/08/04/json-parsing-tutorial
Aakash

Відповіді:


67

Я зробив це двома різними способами,

1.) скласти карту

        HashMap<String, String> applicationSettings = new HashMap<String,String>();
        for(int i=0; i<settings.length(); i++){
            String value = settings.getJSONObject(i).getString("value");
            String name = settings.getJSONObject(i).getString("name");
            applicationSettings.put(name, value);
        }

2.) скласти JSONArray імен

    JSONArray names = json.names();
    JSONArray values = json.toJSONArray(names);
    for(int i=0; i<values.length(); i++){
        if (names.getString(i).equals("description")){
            setDescription(values.getString(i));
        }
        else if (names.getString(i).equals("expiryDate")){
            String dateString = values.getString(i);
            setExpiryDate(stringToDateHelper(dateString)); 
        }
        else if (names.getString(i).equals("id")){
            setId(values.getLong(i));
        }
        else if (names.getString(i).equals("offerCode")){
            setOfferCode(values.getString(i));
        }
        else if (names.getString(i).equals("startDate")){
            String dateString = values.getString(i);
            setStartDate(stringToDateHelper(dateString));
        }
        else if (names.getString(i).equals("title")){
            setTitle(values.getString(i));
        }
    }

335

Я думаю, що цей код короткий і зрозумілий:

int id;
String name;
JSONArray array = new JSONArray(string_of_json_array);
for (int i = 0; i < array.length(); i++) {
    JSONObject row = array.getJSONObject(i);
    id = row.getInt("id");
    name = row.getString("name");
}

Це те, що ви шукали?


3
Приємно і просто! Чудово працює!
Кервін Рамен

5
зауважте, що якщо ви надсилаєте "масив", який не має послідовних номерів, вам доведеться використовувати JSONObject
max4ever

так, це ідеально, але, хоча велика кількість даних, його обробка дуже повільна :(
Ахмад Арслан

@ArslanAhmad Якщо у вас є великий об'єм даних, ви не хочете побудувати весь масив об'єктів json в пам'яті. Натомість використовуйте SAX-подібний підхід. Дивіться тут: stackoverflow.com/questions/10657725 / ...
Vipw

це не працює для мене. я отримую виняток JSON через дужку "{", що оточує об'єкт?
filthy_wizard

7

На жаль, JSONArray не підтримує foreachзаяви, як-от:

for(JSONObject someObj : someJsonArray) {
    // do something about someObj
    ....
    ....
}


це так, але він повертає об'єкт не JSONObject
Помилка

3
Клас JSONArray не реалізує Iterable інтерфейс
Jorgesys

4

Коли я спробував пропозицію @ vipw, я зіткнувся з цим винятком: The method getJSONObject(int) is undefined for the type JSONArray

Натомість це працювало для мене:

int myJsonArraySize = myJsonArray.size();

for (int i = 0; i < myJsonArraySize; i++) {
    JSONObject myJsonObject = (JSONObject) myJsonArray.get(i);

    // Do whatever you have to do to myJsonObject...
}

Для андроїда я замінив замість myJsonArray.size () на myJsonArray.length ()
Rishiraj Purohit

3

Якщо ви використовуєте реалізацію Java JSON.org , яка є відкритим кодом, ви можете просто змусити JSONArray реалізувати Iterableінтерфейс і додати наступний метод до класу:

@Override
public Iterator iterator() {
    return this.myArrayList.iterator();
}

Це зробить всі екземпляри JSONArray ітерабельними, це означає, що for (Object foo : bar)синтаксис тепер буде працювати з ним (зауважте, що foo має бути Об'єктом, оскільки JSONArrays не має оголошеного типу). Все це працює, тому що клас JSONArray підтримується простим ArrayList, який вже є ітерабельним. Я думаю, що інші реалізації з відкритим кодом будуть так само легко змінити.


1
Цікаво, що свого часу реалізація JSON.org мала ітератор у класі JSONArray, але вони видалили його: github.com/douglascrockford/JSON-java/commit/…
vipw

@vipw Я один раз їм по електронній пошті повідомив про реалізацію Iterable, але вони сказали, що в кінцевому підсумку вони не зможуть, оскільки це порушить сумісність з Java 1.4. Можливо, саме тому її зняли в комітеті.
Грім


2

Ви використовуєте один і той же об’єкт Cast для кожного запису. На кожній ітерації ви просто змінювали один і той же об'єкт, а не створювали новий.

Цей код повинен виправити:

JSONArray jCastArr = jObj.getJSONArray("abridged_cast");
ArrayList<Cast> castList= new ArrayList<Cast>();

for (int i=0; i < jCastArr.length(); i++) {
    Cast person = new Cast();  // create a new object here
    JSONObject jpersonObj = jCastArr.getJSONObject(i);

    person.castId = (String) jpersonObj.getString("id");
    person.castFullName = (String) jpersonObj.getString("name");

    castList.add(person);
}
details.castList = castList;

1

Під час ітерації через масив JSON (org.json.JSONArray, вбудований в Android) стежте за нульовими об'єктами; наприклад, ви можете отримати "null"замість нуля рядка.

Чек може виглядати так:

s[i] = array.isNull(i) ? null : array.getString(i);
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.