Bestimmen Sie, ob JSON ein JSONObject oder JSONArray ist

132

Ich werde entweder ein JSON-Objekt oder ein Array vom Server erhalten, aber ich habe keine Ahnung, welches es sein wird. Ich muss mit dem JSON arbeiten, aber dazu muss ich wissen, ob es sich um ein Objekt oder ein Array handelt.

Ich arbeite mit Android.

Hat jemand eine gute Möglichkeit, dies zu tun?

Greg
quelle
Bei der Verwendung von Gson mit Android und wenn es um deserialing eine Art und Weise kommt es zu tun ist , wie diese .
Pirho

Antworten:

244

Ich habe einen besseren Weg gefunden, um festzustellen:

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 kann weitere Typen zurückgeben: http://developer.android.com/reference/org/json/JSONTokener.html#nextValue ()

neworld
quelle
1
gut gemacht. Ich hoffe, es wird sowohl nach JsonObject als auch nach Json Array
Shreyash Mahajan
2
@neworld aber was ist, wenn ich mitten in einer Schleife bin. Wenn Sie versuchen, ein data.getJSONArray () oder ein data.getJSONObject () abzurufen, wird möglicherweise eine JSONEXception ausgelöst !!
P-RAD
Hallo, meine Objektdaten sind mitten in der Antwort. Wie kann ich das erkennen? um zu überprüfen, ob es sich um ein JSONObject oder JSONArray handelt ??? und In Ihrer Antwort String data = "{...}"; hat Wert der gesamten Antwort ???
Amit Pandya
Um dies zu erreichen, müssen Sie Ihren JSON mit analysieren JSONTokener. Ich habe das nicht getan, aber ich nehme an, Sie sollten Past ("your_key") überspringen . Aber ich bin mir nicht sicher. Sie sollten jedoch in Betracht ziehen, json mapper zu verwenden: Gson, Jackson, Moshi und viele andere.
Neworld
53

Es gibt verschiedene Möglichkeiten, dies zu tun:

  1. Sie können das Zeichen an der ersten Position des Strings überprüfen (nachdem Sie Leerzeichen entfernt haben, wie es in gültigem JSON zulässig ist). Wenn es ein ist {, haben Sie es mit einem zu tun JSONObject, wenn es ein ist [, haben Sie es mit einem zu tun JSONArray.
  2. Wenn Sie mit JSON (an Object) zu tun haben, können Sie eine instanceofÜberprüfung durchführen. yourObject instanceof JSONObject. Dies gibt true zurück, wenn yourObject ein JSONObject ist. Gleiches gilt für JSONArray.
nicholas.hauschild
quelle
3
Das hat definitiv funktioniert. Am Ende habe ich die Zeichenfolge in ein JSONObject eingefügt, und wenn ein Fehler aufgetreten ist, wusste ich, dass es sich um ein JSONArray handelt. try {neues JSONObject (json) zurückgeben; } catch (Ausnahme e) {} try {return new JSONArray (json); } catch (Ausnahme e) {}
Greg
3
Ihre erste Option funktioniert nicht zuverlässig, da beim Start von JSON-Daten Leerzeichen zulässig sind. Sie müssen alle führenden Leerzeichen überspringen und das erste Nicht-Leerzeichen überprüfen.
user9876
1
@ user9876 Danke für das Heads Up. Bearbeitet, um Ihren Kommentar wiederzugeben.
nicholas.hauschild
14

Dies ist die einfache Lösung, die ich unter Android verwende:

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
quelle
1
Nicht Android-spezifisch und ich mag diese Version am besten, weil sie keine Zeichenprüfungen verwendet, aber das setzt json.has("data")voraus, dass das Ganze optional ist (nicht gefragt).
Christophe Roussy
7

Einen anderen Weg präsentieren:

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

Hier server_responseist eine Antwortzeichenfolge, die vom Server kommt

Bhargav Thanki
quelle
1

Ein grundlegenderer Weg, dies zu tun, ist der folgende.

JsonArrayist von Natur aus eine Liste

JsonObjectist von Natur aus eine Karte

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
quelle
0

Instanz von

Object.getClass (). GetName ()

Hot Licks
quelle
Ich denke, die Frage geht davon aus, dass Sie mit einer einfachen Zeichenfolge arbeiten, sodass die Verwendung von instanceof oder getClass (). GetName () nicht funktioniert.
Gamerson
@gamerson - Das ist seltsam - es hat viele Male für mich funktioniert. Der Parser muss nur eines der beiden Objekte zurückgeben, anstatt anzugeben, welches.
Hot Licks
1
Offensichtlich verstehen die Leute das nicht. So ziemlich jeder Parser, den ich gesehen habe, hat eine Analyseoption, um eine "JSONInstance" oder einfach "Object" oder was auch immer zurückzugeben. Analysieren Sie den JSON und fragen Sie ihn, was er ist. Ein Parser, der diese Fähigkeit nicht besitzt, ist defekt.
Hot Licks
(Dies ist in der Tat mehr oder weniger Neworlds Antwort.)
Hot Licks
0

Für diejenigen, die dieses Problem in JavaScript angehen, hat das Folgende die Arbeit für mich erledigt (nicht sicher, wie effizient es ist).

if(object.length != undefined) {
   console.log('Array found. Length is : ' + object.length); 
} else {
 console.log('Object found.'); 
}
Raf
quelle
-1

Mein Ansatz wäre eine totale Abstraktion davon. Vielleicht findet das jemand nützlich ...

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


}

Und jetzt dieses Verhalten für immer loswerden ...

...
JSONObject simpleJSONObject = new SimpleJSONObject(jsonObject);
...
oopexpert
quelle