JSONがJSONObjectかJSONArrayかを判別


132

サーバーからJSONオブジェクトまたは配列のいずれかを受信しますが、どちらになるかわかりません。JSONを操作する必要がありますが、そのためには、それがオブジェクトであるか配列であるかを知る必要があります。

Androidを使用しています。

これを行う良い方法はありますか?


AndroidでGsonを使用していて、1つの方法を逆シリアル化する場合は、次のようになり ます
pirho 2018年

回答:


244

私は決定するより良い方法を見つけました:

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はより多くのタイプを返すことができます:http : //developer.android.com/reference/org/json/JSONTokener.html#nextValue()


1
良くやった。JsonObjectとJson Arrayの両方がチェックされることを願っています
Shreyash Mahajan

2
@neworldですが、ループの途中にいる場合はどうなりますか。data.getJSONArray()またはdata.getJSONObject()を取得しようとすると、JSONEXceptionがスローされる可能性があります。
P-RAD、2015

こんにちは私のオブジェクトデータは応答の途中なので、どうやってそれを検出できますか?そのJSONObjectまたはJSONArrayかどうかを確認するには??? そしてあなたの答えではString data = "{...}"; 全体の応答の値を持っていますか???
amit pandya 2017

そのためには、を使用してJSONを解析する必要がありますJSONTokener。私はそれをしませんでしたが、あなたはskipPast( "your_key")をスキップするべきだと思います。しかし、私にはわかりません。ただし、jsonマッパー(Gson、Jackson、Moshiなど)の使用を検討する必要があります。
neworld 2017

53

これを行うには、いくつかの方法があります。

  1. 文字列の最初の位置にある文字をチェックできます(有効なJSONで許可されているため、空白を取り除いた後)。それがの{場合はを処理し、JSONObjectそれがの[場合はを処理しますJSONArray
  2. JSON(an Object)を扱っている場合は、instanceofチェックを行うことができます。 yourObject instanceof JSONObject。yourObjectがJSONObjectの場合、これはtrueを返します。同じことがJSONArrayにも当てはまります。

3
それは間違いなく機能しました。最後に、文字列をJSONObjectに入れ、エラーが発生した場合は、JSONArrayであることがわかりました。{return new JSONObject(json);を試す } catch(例外e){} try {return new JSONArray(json); }キャッチ(例外e){}
グレッグ

3
JSONデータの先頭に空白が許可されているため、最初のオプションは確実に機能しません。先頭の空白をスキップして、最初の空白以外の文字を確認する必要があります。
user9876 2014

1
@ user9876頭を上げてくれてありがとう。あなたのコメントを反映するように編集されました。
nicholas.hauschild 2014

14

これは私が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、

7

別の方法を提示する:

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、サーバからの応答文字列です


1

これを行うためのより基本的な方法は次のとおりです。

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

0

instanceof

Object.getClass()。getName()


私は質問があなたがプレーン文字列で作業することを想定していると思うので、instanceofまたはgetClass()。getName()を使用しても機能しません。
ゲーマーソン2012

@gamerson-それは奇妙です-それは私のために何度も働いています。パーサーにどちらかのオブジェクトを返すか、どちらを指定するかを指定するだけです。
ホットリックス

1
明らかに人々はこれを理解していません。私が見たほとんどすべてのパーサーには、「JSONInstance」または単に「オブジェクト」などを返す解析オプションがあります。JSONを解析して、それが何であるかを尋ねます。この機能を持たないパーサーは壊れています。
Hot Licks 2014

(これは、実際には、Neworldの回答です。多かれ少なかれです。)
Hot Licks 14

0

JavaScriptでこの問題に取り組む人たちのために、以下は私のために仕事をしました(それがどれほど効率的かはわかりません)。

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

-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);
...
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.