Determinar se JSON é um JSONObject ou JSONArray

132

Vou receber um objeto JSON ou uma matriz do servidor, mas não tenho idéia de qual será. Preciso trabalhar com o JSON, mas para fazer isso, preciso saber se é um Objeto ou uma Matriz.

Estou trabalhando com Android.

Alguém tem uma boa maneira de fazer isso?

Greg
fonte
Se estiver usando Gson com Android e quando se trata de deserialing uma maneira de fazê-lo é como este .
Pirho # 12/18

Respostas:

244

Encontrei uma maneira melhor 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

o tokenizer pode retornar mais tipos: http://developer.android.com/reference/org/json/JSONTokener.html#nextValue ()

novo mundo
fonte
1
bom trabalho. espero que ele irá verificar se há tanto JSONObject e JSON matriz
Shreyash Mahajan
2
@neworld, mas e se eu estiver no meio de um loop. tentar obter um data.getJSONArray () ou data.getJSONObject () potencialmente lançará uma JSONEXception !!
P-RAD
Olá, meus dados de objeto estão no meio da resposta, então como posso detectar isso? verificar se é um JSONObject ou JSONArray ??? e Na sua resposta String data = "{...}"; está tendo valor de resposta inteira ???
Amit pandya
Para fazer isso, você precisa analisar seu JSON usando JSONTokener. Não fiz isso, mas suponho que você deveria pularPast ("sua_chave") . Mas eu não tenho certeza. No entanto, você deve considerar o uso do json mapper: Gson, Jackson, Moshi e muitos outros.
New30 de
53

Existem algumas maneiras de fazer isso:

  1. Você pode verificar o caractere na primeira posição da String (após aparar o espaço em branco, como é permitido no JSON válido). Se é a {, você está lidando com a JSONObject, se é a [, você está lidando com a JSONArray.
  2. Se você estiver lidando com JSON (an Object), poderá fazer uma instanceofverificação. yourObject instanceof JSONObject. Isso retornará true se yourObject for um JSONObject. O mesmo se aplica ao JSONArray.
nicholas.hauschild
fonte
3
Isso definitivamente funcionou. No final, porém, coloquei a string em um JSONObject e, se isso gerasse um erro, sabia que era um JSONArray. tente {retornar novo JSONObject (json); } catch (Exceção e) {} try {return new JSONArray (json); } catch (Exceção e) {}
Greg
3
Sua primeira opção não funcionará de maneira confiável, porque espaço em branco é permitido no início dos dados JSON. Você precisa pular qualquer espaço em branco à esquerda e verificar o primeiro caractere que não seja em espaço em branco.
user9876
1
@ user9876 Obrigado pelo aviso. Editado para refletir seu comentário.
Nicholas.hauschild
14

Esta é a solução simples que estou usando no 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
fonte
1
Não é específico para Android e eu gosto mais desta versão porque ela não usa verificações de caracteres, mas json.has("data")supõe que a coisa toda é opcional (não solicitada).
Christophe Roussy 02/02
7

Apresentando uma outra maneira:

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

Aqui server_responseestá uma resposta String vinda do servidor

Bhargav Thanki
fonte
1

Uma maneira mais fundamental de fazer isso é o seguinte.

JsonArrayé inerentemente uma lista

JsonObjecté inerentemente um 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
fonte
0

instancia de

Object.getClass (). GetName ()

Hot Licks
fonte
Eu acho que a pergunta assume que você estará trabalhando com uma string simples, portanto, usando a instanceof ou getClass (). GetName () não funcionará.
gamerson
@amerson - Isso é estranho - já funcionou para mim muitas vezes. Você só precisa que o analisador retorne um ou outro objeto, versus especificando qual.
Hot Licks
1
Claramente, as pessoas não entendem isso. Praticamente todos os analisadores que eu vi têm uma opção de análise para retornar um "JSONInstance" ou simplesmente "Objeto", ou o que seja. Analise o JSON e pergunte o que é. Um analisador que não tem essa capacidade está quebrado.
Hot Licks
(Isto é, de fato, a resposta de Neworld, mais ou menos.)
Hot Licks
0

Para aqueles que enfrentam esse problema no JavaScript, o seguinte foi o meu trabalho (não tenho certeza de quão eficiente é).

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

Minha abordagem seria uma abstração total disso. Talvez alguém ache isso ú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;
    }


}

E agora se livre desse comportamento para sempre ...

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