Определите, является ли JSON JSONObject или JSONArray

132

Я собираюсь получить с сервера либо объект JSON, либо массив, но понятия не имею, что это будет. Мне нужно работать с JSON, но для этого мне нужно знать, является ли он объектом или массивом.

Я работаю с Android.

Есть ли у кого-нибудь хороший способ сделать это?

Greg
источник
При использовании Gson с Android , и когда дело доходит до deserialing один из способов сделать это, как это .
pirho

Ответы:

244

Я нашел лучший способ определить:

String data = "{ ... }";
Object json = new JSONTokener(data).nextValue();
if (json instanceof JSONObject)
  //you have an object
else if (json instanceof JSONArray)
  //you have an array

tokenizer может возвращать больше типов: http://developer.android.com/reference/org/json/JSONTokener.html#nextValue ()

neworld
источник
1
хорошая работа. надеюсь, что он проверит как JsonObject, так и Json Array
Шреяш Махаджан
2
@neworld, но что, если я нахожусь в середине цикла. попытка получить data.getJSONArray () или data.getJSONObject () потенциально вызовет JSONEXception !!
P-RAD
Привет, мои объектные данные находятся в середине ответа, как я могу это определить? чтобы проверить, является ли это JSONObject или JSONArray ??? и в вашем ответе String data = "{...}"; имеет значение всего ответа ???
амит пандья
Для этого вам нужно проанализировать свой JSON с помощью JSONTokener. Я этого не делал, но полагаю, вам следует пропуститьPast ("your_key") . Но я не уверен. Однако вам следует подумать об использовании json mapper: Gson, Jackson, Moshi и многих других.
neworld
53

Это можно сделать двумя способами:

  1. Вы можете проверить символ в первой позиции строки (после удаления пробелов, как это разрешено в допустимом JSON). Если это a {, вы имеете дело с a JSONObject, если это a [, вы имеете дело с a JSONArray.
  2. Если вы имеете дело с JSON (an Object), вы можете выполнить instanceofпроверку. yourObject instanceof JSONObject, Это вернет истину, если yourObject является JSONObject. То же самое и с JSONArray.
nicholas.hauschild
источник
3
Это определенно сработало. В конце концов, я поместил строку в JSONObject, и если она выдала ошибку, то я знал, что это JSONArray. попробуйте {вернуть новый объект JSONObject (json); } catch (исключение e) {} try {return new JSONArray (json); } catch (Exception e) {}
Грег,
3
Ваш первый вариант не будет работать надежно, потому что в начале данных JSON разрешены пробелы. Вам нужно пропустить любые ведущие пробелы и проверить первый непробельный символ.
user9876
1
@ user9876 Спасибо за внимание. Отредактировано, чтобы отразить ваш комментарий.
nicholas.hauschild
14

Это простое решение, которое я использую на Android:

JSONObject json = new JSONObject(jsonString);

if (json.has("data")) {

    JSONObject dataObject = json.optJSONObject("data");

    if (dataObject != null) {

        //Do things with object.

    } else {

        JSONArray array = json.optJSONArray("data");

        //Do things with array
    }
} else {
    // Do nothing or throw exception if "data" is a mandatory field
}
sourcerebels
источник
1
Не для Android, и мне больше всего нравится эта версия, потому что она не использует проверки символов, но json.has("data")предполагает, что все это необязательно (не запрашивается).
Christophe Roussy
7

Представляя другой способ:

if(server_response.trim().charAt(0) == '[') {
    Log.e("Response is : " , "JSONArray");
} else if(server_response.trim().charAt(0) == '{') {
    Log.e("Response is : " , "JSONObject");
}

Вот server_responseстрока ответа, поступающая с сервера

Бхаргав Благодар
источник
1

Более фундаментальный способ сделать это следующий.

JsonArrayпо своей сути является списком

JsonObjectпо сути является картой

if (object instanceof Map){
    JSONObject jsonObject = new JSONObject();
    jsonObject.putAll((Map)object);
    ...
    ...
}
else if (object instanceof List){
    JSONArray jsonArray = new JSONArray();
    jsonArray.addAll((List)object);
    ...
    ...
}
Панкадж Сингхал
источник
0

случай

Object.getClass (). GetName ()

Горячие лижет
источник
Я думаю, что вопрос предполагает, что вы будете работать с простой строкой, поэтому использование instanceof или getClass (). GetName () не будет работать.
gamerson
@gamerson - Странно - у меня это срабатывало много раз. Вам просто нужно, чтобы парсер возвращал любой объект, а не указывал какой.
Hot Licks
1
Ясно, что люди этого не понимают. Практически каждый синтаксический анализатор, который я видел, имеет параметр синтаксического анализа, возвращающий "JSONInstance" или просто "Object" или что-то еще. Разберите JSON и спросите, что это такое. Парсер, у которого нет этой возможности, сломан.
Hot Licks
(Фактически, это более или менее ответ Neworld.)
Hot Licks
0

Для тех, кто решает эту проблему с помощью JavaScript, я сделал следующее (не уверен, насколько это эффективно).

if(object.length != undefined) {
   console.log('Array found. Length is : ' + object.length); 
} else {
 console.log('Object found.'); 
}
Raf
источник
-1

Мой подход был бы полной абстракцией от этого. Может, кому-то это пригодится ...

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

public class SimpleJSONObject extends JSONObject {


    private static final String FIELDNAME_NAME_VALUE_PAIRS = "nameValuePairs";


    public SimpleJSONObject(String string) throws JSONException {
        super(string);
    }


    public SimpleJSONObject(JSONObject jsonObject) throws JSONException {
        super(jsonObject.toString());
    }


    @Override
    public JSONObject getJSONObject(String name) throws JSONException {

        final JSONObject jsonObject = super.getJSONObject(name);

        return new SimpleJSONObject(jsonObject.toString());
    }


    @Override
    public JSONArray getJSONArray(String name) throws JSONException {

        JSONArray jsonArray = null;

        try {

            final Map<String, Object> map = this.getKeyValueMap();

            final Object value = map.get(name);

            jsonArray = this.evaluateJSONArray(name, value);

        } catch (Exception e) {

            throw new RuntimeException(e);

        }

        return jsonArray;
    }


    private JSONArray evaluateJSONArray(String name, final Object value) throws JSONException {

        JSONArray jsonArray = null;

        if (value instanceof JSONArray) {

            jsonArray = this.castToJSONArray(value);

        } else if (value instanceof JSONObject) {

            jsonArray = this.createCollectionWithOneElement(value);

        } else {

            jsonArray = super.getJSONArray(name);

        }
        return jsonArray;
    }


    private JSONArray createCollectionWithOneElement(final Object value) {

        final Collection<Object> collection = new ArrayList<Object>();
        collection.add(value);

        return (JSONArray) new JSONArray(collection);
    }


    private JSONArray castToJSONArray(final Object value) {
        return (JSONArray) value;
    }


    private Map<String, Object> getKeyValueMap() throws NoSuchFieldException, IllegalAccessException {

        final Field declaredField = JSONObject.class.getDeclaredField(FIELDNAME_NAME_VALUE_PAIRS);
        declaredField.setAccessible(true);

        @SuppressWarnings("unchecked")
        final Map<String, Object> map = (Map<String, Object>) declaredField.get(this);

        return map;
    }


}

А теперь избавься от этого поведения навсегда ...

...
JSONObject simpleJSONObject = new SimpleJSONObject(jsonObject);
...
oopexpert
источник