Determine si JSON es un JSONObject o JSONArray

132

Voy a recibir un objeto JSON o una matriz del servidor, pero no tengo idea de cuál será. Necesito trabajar con el JSON, pero para hacerlo, necesito saber si es un objeto o una matriz.

Estoy trabajando con Android

¿Alguien tiene una buena manera de hacer esto?

Greg
fuente
Si se utiliza Gson con Android y cuando se trata de deserialing una forma de hacerlo es como este .
pirho

Respuestas:

244

Encontré una mejor manera de determinar:

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 puede devolver más tipos: http://developer.android.com/reference/org/json/JSONTokener.html#nextValue ()

nuevo mundo
fuente
1
buen trabajo. espero que verifique tanto JsonObject como Json Array
Shreyash Mahajan
2
@neworld, pero ¿qué pasa si estoy en medio de un bucle? tratando de obtener un data.getJSONArray () o data.getJSONObject () potencialmente arrojará una JSONEXception !!
P-RAD
Hola, mis datos de objeto son medios de respuesta, ¿cómo puedo detectar eso? para verificar si es un JSONObject o JSONArray ??? y en su respuesta String data = "{...}"; ¿Está teniendo valor de respuesta completa?
amit pandya
Para lograr eso, debes analizar tu JSON usando JSONTokener. No hice eso, pero supongo que deberías omitir Pasado ("tu_clave") . Pero no estoy seguro. Sin embargo, debería considerar usar json mapper: Gson, Jackson, Moshi y muchos otros.
neworld
53

Hay un par de formas de hacer esto:

  1. Puede verificar el carácter en la primera posición de la Cadena (después de recortar los espacios en blanco, ya que está permitido en un JSON válido). Si es un {, estás tratando con un JSONObject, si es un [, estás tratando con un JSONArray.
  2. Si está tratando con JSON (an Object), puede hacer una instanceofverificación. yourObject instanceof JSONObject. Esto devolverá verdadero si yourObject es un JSONObject. Lo mismo se aplica a JSONArray.
nicholas.hauschild
fuente
3
Eso definitivamente funcionó. Al final, sin embargo, puse la cadena en un JSONObject y si arrojó un error, entonces supe que era un JSONArray. try {return new JSONObject (json); } catch (Excepción e) {} try {return new JSONArray (json); } catch (Exception e) {}
Greg
3
Su primera opción no funcionará de manera confiable, ya que se permiten espacios en blanco al comienzo de los datos JSON. Debe omitir cualquier espacio en blanco inicial y verificar el primer carácter que no sea un espacio en blanco.
user9876
1
@ user9876 Gracias por el aviso. Editado para reflejar tu comentario.
nicholas.hauschild
14

Esta es la solución simple que estoy usando en 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
}
rebeldes
fuente
1
No es específico de Android y me gusta más esta versión porque no utiliza verificaciones de caracteres, pero json.has("data")supone que todo es opcional (no solicitado).
Christophe Roussy
7

Presentando otra forma:

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

Aquí server_responsehay una cadena de respuesta que viene del servidor

Bhargav Thanki
fuente
1

Una forma más fundamental de hacer esto es la siguiente.

JsonArrayes inherentemente una lista

JsonObjectes inherentemente un mapa

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

en vez de

Object.getClass (). GetName ()

Hot Licks
fuente
Creo que la pregunta asume que trabajará con una cadena simple, por lo que usar la instancia de o getClass (). GetName () no funcionará.
gamerson
@gamerson - Eso es extraño, me ha funcionado muchas veces. Solo tiene que hacer que el analizador devuelva cualquier objeto, en lugar de especificar cuál.
Hot Licks
1
Claramente la gente no entiende esto. Casi todos los analizadores que he visto tienen una opción de análisis para devolver una "JSONInstance" o simplemente "Object", o lo que sea. Analiza el JSON y luego pregúntale qué es. Un analizador que no tiene esta habilidad está roto.
Hot Licks el
(Esta es, de hecho, la respuesta de Neworld, más o menos.)
Hot Licks
0

Para aquellos que abordan este problema en JavaScript, lo siguiente hizo el trabajo por mí (no estoy seguro de cuán eficiente es).

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

Mi enfoque sería una abstracción total de esto. Tal vez alguien encuentre esto útil ...

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


}

Y ahora deshazte de este comportamiento para siempre ...

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