判断JSON是JSONObject还是JSONArray。

141

我将从服务器收到JSON对象或数组,但我不知道它会是哪一个。我需要处理这个JSON,但要这样做,我需要知道它是一个对象还是一个数组。

我正在使用安卓系统。

有没有好的方法可以处理这个问题?


如果在Android中使用Gson,并且在反序列化方面,一种方法是像这样 - pirho
9个回答

261

1
干得好。希望它可以检查JsonObject和Json Array两者。 - Shreyash Mahajan
2
@neworld 但是如果我正在循环中,尝试获取 data.getJSONArray() 或 data.getJSONObject() 可能会抛出一个 JSONEXception! - P-RAD
嗨,我的objectdata在响应的中间,我该如何检测它是JSONObject还是JSONArray?在你的回答中,String data = "{ ... }";是否包含整个响应的值? - amit pandya
为了实现这一点,您必须使用JSONTokener解析您的JSON。我没有这样做,但我认为您应该skipPast("your_key")。但我不确定。然而,您应该考虑使用json映射器:Gson、Jackson、Moshi和其他大量工具。 - neworld

55

你可以有几种方法来完成这个操作:

  1. 您可以检查 String 的第一个位置上的字符(在修剪掉空格后,因为它在有效的 JSON 中是允许的)。如果是 {,则您正在处理 JSONObject;如果是 [,则您正在处理 JSONArray
  2. 如果您正在处理 JSON(一个 Object),那么您可以进行 instanceof 检查。 yourObject instanceof JSONObject。 如果 yourObject 是 JSONObject,则返回 true。对于 JSONArray 也适用。

3
那肯定有效。不过最后,我将字符串放入 JSONObject 中,如果出错了,那就是 JSONArray。尝试如下代码:try { return new JSONObject(json); } catch (Exception e) { }try { return new JSONArray(json); } catch (Exception e) { } - Greg

15

这是我在 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
}

1
这不是针对Android特定的内容,我喜欢这个版本最好,因为它不使用字符检查,但是json.has("data")假设整个内容都是可选的(没有要求)。 - Christophe Roussy

8

介绍另一种方法:

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

这里的server_response是来自服务器的响应字符串。


2
更基本的做法如下。 JsonArray 本质上是一个列表JsonObject 本质上是一个映射
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);
    ...
    ...
}

注意,这不适用于org.json(不继承自List或Map),只适用于javax.json(jakarta.json-api)。在这里的一种方法是尝试使用数组,如果失败,则捕获并尝试对象。 - Boris Krassi

0

对于那些在JavaScript中解决这个问题的人,以下代码对我很有用(不确定它的效率如何)。

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

0

instanceof

Object.getClass().getName()


我认为这个问题假设你将使用一个普通字符串,因此使用instanceof或getClass().getName()是行不通的。 - gamerson
@gamerson -- 这很奇怪 -- 对我来说已经多次成功了。你只需要让解析器返回对象,而不是指定哪个对象。 - Hot Licks
1
显然有些人不理解这一点。几乎我所见过的每一个解析器都有一个解析选项来返回“JSONInstance”或简单地返回“Object”,或其他什么类型的数据。解析JSON,然后询问它是什么。一个没有此功能的解析器是有缺陷的。 - Hot Licks
(这实际上是Neworld的答案,或多或少。) - Hot Licks

0
JsonNode jsonNode=mapper.readTree(patchBody);

jsonNode有两个方法:
isObject();
isArray();


-1

我的方法是完全抽象化的。也许有人会觉得这很有用...

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


}

现在永远摆脱这种行为...

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接