Déterminer si JSON est un JSONObject ou JSONArray

132

Je vais recevoir un objet JSON ou un tableau du serveur, mais je n'ai aucune idée de ce que ce sera. J'ai besoin de travailler avec le JSON, mais pour ce faire, j'ai besoin de savoir s'il s'agit d'un objet ou d'un tableau.

Je travaille avec Android.

Quelqu'un a-t-il un bon moyen de faire cela?

Greg
la source
Si vous utilisez Gson avec Android et quand il s'agit de désérialiser, une façon de le faire est la suivante .
pirho

Réponses:

244

J'ai trouvé un meilleur moyen de déterminer:

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 est capable de renvoyer plus de types: http://developer.android.com/reference/org/json/JSONTokener.html#nextValue ()

nouveau monde
la source
1
Bon travail. J'espère qu'il vérifiera à la fois JsonObject et Json Array
Shreyash Mahajan
2
@neworld mais que faire si je suis au milieu d'une boucle. essayer d'obtenir un data.getJSONArray () ou data.getJSONObject () lancera potentiellement une JSONEXception !!
P-RAD
Salut mes objectdata sont au milieu de la réponse, alors comment puis-je détecter cela? pour vérifier si c'est un JSONObject ou JSONArray ??? et Dans votre réponse String data = "{...}"; a la valeur de la réponse entière ???
amit pandya
Pour ce faire, vous devez analyser votre JSON en utilisant JSONTokener. Je n'ai pas fait ça, mais je suppose que vous devriez skipPast ("your_key") . Mais je ne suis pas sûr. Cependant, vous devriez envisager d'utiliser le mappeur json: Gson, Jackson, Moshi et bien d'autres.
neworld
53

Vous pouvez procéder de plusieurs manières:

  1. Vous pouvez vérifier le caractère à la première position de la chaîne (après avoir coupé les espaces, comme cela est autorisé dans un JSON valide). Si c'est un {, vous avez affaire à un JSONObject, si c'est un [, vous avez affaire à un JSONArray.
  2. Si vous avez affaire à JSON (an Object), vous pouvez effectuer une instanceofvérification. yourObject instanceof JSONObject. Cela retournera true si votreObjet est un JSONObject. La même chose s'applique à JSONArray.
nicholas.hauschild
la source
3
Cela a vraiment fonctionné. En fin de compte cependant, j'ai mis la chaîne dans un JSONObject et si cela provoquait une erreur, je savais que c'était un JSONArray. try {return new JSONObject (json); } catch (Exception e) {} try {return new JSONArray (json); } catch (Exception e) {}
Greg
3
Votre première option ne fonctionnera pas de manière fiable, car les espaces sont autorisés au début des données JSON. Vous devez ignorer tous les espaces de début et vérifier le premier caractère non blanc.
user9876
1
@ user9876 Merci pour la mise en garde. Modifié pour refléter votre commentaire.
nicholas.hauschild
14

Voici la solution simple que j'utilise sur 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
la source
1
Pas spécifique à Android et j'aime mieux cette version car elle n'utilise pas de vérification de caractères, mais json.has("data")suppose que tout est facultatif (non demandé).
Christophe Roussy le
7

Présenter d'une autre manière:

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

Voici server_responseune chaîne de réponse provenant du serveur

Bhargav Thanki
la source
1

Une manière plus fondamentale de procéder est la suivante.

JsonArrayest intrinsèquement une liste

JsonObjectest intrinsèquement une carte

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
la source
0

exemple de

Object.getClass (). GetName ()

Hot Licks
la source
Je pense que la question suppose que vous travaillerez avec une chaîne simple, donc utiliser instanceof ou getClass (). GetName () ne fonctionnera pas.
gamerson
@gamerson - C'est étrange - cela a fonctionné pour moi plusieurs fois. Il suffit que l'analyseur renvoie l'un ou l'autre des objets, plutôt que de spécifier lequel.
Hot Licks
1
De toute évidence, les gens ne comprennent pas cela. Presque tous les analyseurs que j'ai vus ont une option d'analyse pour retourner un "JSONInstance" ou simplement un "Object", ou autre. Analysez le JSON, puis demandez-lui ce que c'est. Un analyseur qui n'a pas cette capacité est cassé.
Hot Licks
(C'est, en fait, la réponse de Neworld, plus ou moins.)
Hot Licks
0

Pour ceux qui s'attaquent à ce problème en JavaScript, ce qui suit a fait le travail pour moi (je ne suis pas sûr de son efficacité).

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

Mon approche en serait une abstraction totale. Peut-être que quelqu'un trouve cela utile ...

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


}

Et maintenant débarrassez-vous de ce comportement pour toujours ...

...
JSONObject simpleJSONObject = new SimpleJSONObject(jsonObject);
...
oopexpert
la source