Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert a Bundle to JSON

I'd like to convert the an Intent's extras Bundle into a JSONObject so that I can pass it to/from JavaScript.

Is there a quick or best way to do this conversion? It would be alright if not all possible Bundles will work.

like image 781
Murph Avatar asked Feb 18 '14 15:02

Murph


4 Answers

You can use Bundle#keySet() to get a list of keys that a Bundle contains. You can then iterate through those keys and add each key-value pair into a JSONObject:

JSONObject json = new JSONObject();
Set<String> keys = bundle.keySet();
for (String key : keys) {
    try {
        // json.put(key, bundle.get(key)); see edit below
        json.put(key, JSONObject.wrap(bundle.get(key)));
    } catch(JSONException e) {
        //Handle exception here
    }
}

Note that JSONObject#put will require you to catch a JSONException.

Edit:

It was pointed out that the previous code didn't handle Collection and Map types very well. If you're using API 19 or higher, there's a JSONObject#wrap method that will help if that's important to you. From the docs:

Wrap an object, if necessary. If the object is null, return the NULL object. If it is an array or collection, wrap it in a JSONArray. If it is a map, wrap it in a JSONObject. If it is a standard property (Double, String, et al) then it is already wrapped. Otherwise, if it comes from one of the java packages, turn it into a string. And if it doesn't, try to wrap it in a JSONObject. If the wrapping fails, then null is returned.

like image 119
Makario Avatar answered Nov 17 '22 18:11

Makario


private String getJson(final Bundle bundle) {
    if (bundle == null) return null;
    JSONObject jsonObject = new JSONObject();

    for (String key : bundle.keySet()) {
        Object obj = bundle.get(key);
        try {
            jsonObject.put(key, wrap(bundle.get(key)));
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    return jsonObject.toString();
}

public static Object wrap(Object o) {
    if (o == null) {
        return JSONObject.NULL;
    }
    if (o instanceof JSONArray || o instanceof JSONObject) {
        return o;
    }
    if (o.equals(JSONObject.NULL)) {
        return o;
    }
    try {
        if (o instanceof Collection) {
            return new JSONArray((Collection) o);
        } else if (o.getClass().isArray()) {
            return toJSONArray(o);
        }
        if (o instanceof Map) {
            return new JSONObject((Map) o);
        }
        if (o instanceof Boolean ||
                o instanceof Byte ||
                o instanceof Character ||
                o instanceof Double ||
                o instanceof Float ||
                o instanceof Integer ||
                o instanceof Long ||
                o instanceof Short ||
                o instanceof String) {
            return o;
        }
        if (o.getClass().getPackage().getName().startsWith("java.")) {
            return o.toString();
        }
    } catch (Exception ignored) {
    }
    return null;
}

public static JSONArray toJSONArray(Object array) throws JSONException {
    JSONArray result = new JSONArray();
    if (!array.getClass().isArray()) {
        throw new JSONException("Not a primitive array: " + array.getClass());
    }
    final int length = Array.getLength(array);
    for (int i = 0; i < length; ++i) {
        result.put(wrap(Array.get(array, i)));
    }
    return result;
}
like image 21
Dmitry Avatar answered Nov 17 '22 18:11

Dmitry


Here is a Gson type adapter factory that converts a Bundle to JSON.

https://github.com/google-gson/typeadapters/blob/master/android/src/main/java/BundleTypeAdapterFactory.java

like image 3
inder Avatar answered Nov 17 '22 18:11

inder


If the bundle has nested bundles then JSONObject.wrap(bundle.get(key)) will return null. So I managed to get it to work for my use case with this recursive function. Haven't tested more advanced use cases though.

JSONObject json = convertBundleToJson(bundle);

public JSONObject convertBundleToJson(Bundle bundle) {
    JSONObject json = new JSONObject();
    Set<String> keys = bundle.keySet();

    for (String key : keys) {
        try {
            if (bundle.get(key) != null && bundle.get(key).getClass().getName().equals("android.os.Bundle")) {
                Bundle nestedBundle = (Bundle) bundle.get(key);
                json.put(key, convertToJson(nestedBundle));
            } else {
                json.put(key, JSONObject.wrap(bundle.get(key)));
            }
        } catch(JSONException e) {
            System.out.println(e.toString());
        }
    }

    return json;
}
like image 1
RLU Avatar answered Nov 17 '22 19:11

RLU