Określ, czy JSON jest JSONObject czy JSONArray

135

Mam zamiar otrzymać obiekt JSON lub tablicę z serwera, ale nie mam pojęcia, który to będzie. Muszę pracować z JSON, ale aby to zrobić, muszę wiedzieć, czy jest to obiekt czy tablica.

Pracuję z Androidem.

Czy ktoś ma dobry sposób na zrobienie tego?

Greg
źródło
W przypadku korzystania z systemu Android Gson a jeśli chodzi o deserialing jeden sposób, aby zrobić to jak ten .
pirho

Odpowiedzi:

249

Znalazłem lepszy sposób na określenie:

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 jest w stanie zwrócić więcej typów: http://developer.android.com/reference/org/json/JSONTokener.html#nextValue ()

nowy świat
źródło
1
dobra robota. mam nadzieję, że sprawdzi zarówno JsonObject, jak i Json Array
Shreyash Mahajan
2
@neworld, ale co, jeśli jestem w środku pętli. próba pobrania data.getJSONArray () lub data.getJSONObject () potencjalnie wyrzuci wyjątek JSONEXception !!
P-RAD
Cześć, moje dane obiektu są w połowie odpowiedzi, więc jak mogę to wykryć? sprawdzić, czy jest to JSONObject czy JSONArray ??? i W swojej odpowiedzi String data = "{...}"; ma wartość całej odpowiedzi ???
amit pandya
Aby to osiągnąć, musisz przeanalizować swój JSON przy użyciu JSONTokener. Nie zrobiłem tego, ale przypuszczam, że powinieneś pominąćPast ("twój_klucz") . Ale nie jestem pewien. Jednak powinieneś rozważyć użycie json mapper: Gson, Jackson, Moshi i mnóstwo innych.
neworld
54

Możesz to zrobić na kilka sposobów:

  1. Możesz sprawdzić znak na pierwszej pozycji ciągu (po usunięciu białych znaków, ponieważ jest to dozwolone w prawidłowym formacie JSON). Jeśli jest to {, masz do czynienia z a JSONObject, jeśli jest to [, masz do czynienia z JSONArray.
  2. Jeśli masz do czynienia z JSON (an Object), możesz instanceofsprawdzić. yourObject instanceof JSONObject. Zwróci to wartość true, jeśli yourObject jest JSONObject. To samo dotyczy JSONArray.
nicholas.hauschild
źródło
3
To zdecydowanie zadziałało. Ostatecznie jednak umieściłem ciąg w JSONObject i jeśli wyrzucił błąd, wiedziałem, że to JSONArray. try {return new JSONObject (json); } catch (wyjątek e) {} try {return new JSONArray (json); } catch (wyjątek e) {}
Greg
3
Twoja pierwsza opcja nie będzie działać niezawodnie, ponieważ białe znaki są dozwolone na początku danych JSON. Musisz pominąć wszelkie początkowe spacje i sprawdzić pierwszy znak niebędący białymi znakami.
user9876
1
@ user9876 Dzięki za ostrzeżenia. Zmieniono, aby odzwierciedlić Twój komentarz
nicholas.hauschild
14

Oto proste rozwiązanie, którego używam na Androidzie:

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
źródło
1
Nie jest specyficzna dla Androida i najbardziej podoba mi się ta wersja, ponieważ nie używa sprawdzania znaków, ale json.has("data")zakłada, że ​​całość jest opcjonalna (nie jest wymagana).
Christophe Roussy
7

Przedstawiamy inny sposób:

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

Oto server_responseciąg odpowiedzi pochodzący z serwera

Bhargav Thanki
źródło
1

Bardziej podstawowy sposób wykonania tego jest następujący.

JsonArrayjest z natury Listą

JsonObjectjest z natury mapą

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);
    ...
    ...
}
Pankaj Singhal
źródło
0

wystąpienie

Object.getClass (). GetName ()

Hot Licks
źródło
Myślę, że pytanie zakłada, że ​​będziesz pracować ze zwykłym ciągiem znaków, więc użycie funkcji instanceof lub getClass (). GetName () nie zadziała.
gamerson,
@gamerson - To dziwne - działało na mnie wiele razy. Wystarczy, że parser zwróci jeden z obiektów, zamiast określać który.
Hot Licks,
1
Najwyraźniej ludzie tego nie rozumieją. Prawie każdy parser, jaki widziałem, ma opcję parsowania, aby zwrócić „JSONInstance” lub po prostu „Object”, lub cokolwiek innego. Przeanalizuj JSON, a następnie zapytaj, co to jest. Parser, który nie ma tej możliwości, jest uszkodzony.
Hot Licks
(W rzeczywistości jest to mniej więcej odpowiedź Neworld.)
Hot Licks
0

Dla tych, którzy zajmują się tym problemem w JavaScript, wykonałem zadanie za mnie (nie jestem pewien, jak wydajne jest to).

if(object.length != undefined) {
   console.log('Array found. Length is : ' + object.length); 
} else {
 console.log('Object found.'); 
}
Raf
źródło
-1

Moje podejście byłoby całkowitą abstrakcją. Może ktoś uzna to za przydatne ...

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;
    }


}

A teraz pozbądź się tego zachowania na zawsze ...

...
JSONObject simpleJSONObject = new SimpleJSONObject(jsonObject);
...
oopexpert
źródło