Skip to content
Daniel Bergløv edited this page Jul 13, 2015 · 4 revisions

Back to Home


If you want to parse an object between multiple processes, you would naturally implement the Parcelable interface and have all your object's data written to a Parcel before sending it. The downside to the Parcel is that it needs manual implementation on how to handle data both in and out. The upside though is that it takes very little time to do this work, since Parcels are very simple in their structure.

One more downside with Parcels is that they cannot help you if you want to parse the object over a network or store the data to a database. You might do some small tricks to do so, but it would not be recommendable seen as the Parcel implementation might not be exact between platform versions. The best solution for this would be to write everything to a JSON string. The problem though is that the JSON tools are not as simple as the Parcel You need to create Objects/Arrays, iterate through Lists and Arrays and more. The whole process can become quite cluttered and takes a lot more time, depending on your data.

The JSONParcel is a JSON like version of Parcel. I say JSON like, because due to it's optimizations it does not provide a string that is compatible with a normal JSON decoder. But it does provide a string output that is safe to parse between networks and add to a persistent storage. It does so using similar tools and structure as the normal Parcel making the process just as easy without the clutter. It's JSONParcelable interface is also made compatible with Parcelable so that you can easily implement both in the same class. One for Network/Storage and one for parsing between processes.

Example 1

public class MyClass implements JSONParcelable {

    private List<String> mList;
    private Set<Integer> mSet;
    private byte[] mBytes;
    private String mString;
    private JSONParcelable mObject;

    public MyClass(JSONParcel source, ClassLoader loader) {
        mList = source.readList();
        mSet = source.readSet();
        mBytes = source.readByteArray();
        mString = source.readString();
        mObject = source.readJSONParselable(loader);
    }

    @Override
    public void writeToJSON(JSONParcel dest) throws JSONException {
        dest.writeList(mList);
        dest.writeSet(mSet);
        dest.writeByteArray(mBytes);
        dest.writeString(mString);
        dest.writeJSONParcelable(mObject);
    }

    public static CREATOR = new JSONParcelable.Creator<MyClass>() {
        @Override
        public MyClass createFromParcel(Parcel source) throws JSONException {
            return new MyClass(source, loader);
        }

        @Override
        public MyClass[] newArray(int size) {
            return new MyClass[size];
        }
    }
}

Now all you need is to send this object to somewhere

// Create an instance of our class
MyClass instance = new MyClass();

// Create a new JSONParcel
JSONParcel parcel = new JSONParcel();

// Add the class to the parcel
parcel.writeJSONParcelable(instance);

// Send the data to somewhere
doSomethingWithData(parcel.toString());

The parcel.toString() will output something like the below, depending on the data.

[i3,d4.86E11,l19678678656,s8vE23FWv55EVbnNUi6=,i9178139]

This is where it differs from normal JSON output as the first character of each entry defines the data type, which can be Integer(i), Long(l), Float(f), Double(d), Character(c), Byte(b) or String(s). All String(s) entries are compressed with gzip and encoded with Base64 using URI safe option.

It is just as easy to re-create the object from the parcel data

// Get the string representation of our parceled data
String data = getDataFromSomeWhere();

// Place the data in a new JSONParcel
JSONParsel parcel = new JSONParcel(data);

// Re-create the object
MyClass instance = parcel.readJSONParcelable(MyClass.class.getClassLoader());

Example 2

In order to easier work with both parcel types, JSONParcel's also uses the static field CREATOR for it's creator interface. And it also has a convenience interface for more quickly adding support for both.

public class MyClass implements MultiParcelable {

    @Override
    public void writeToJSON(JSONParcel dest) throws JSONException {

    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {

    }

    public static MultiCreator<MyClass> CREATOR = new MultiCreator<MyClass>() {
        @Override
        public MyClass createFromParcel(Parcel source) {

        }

        @Override
        public MyClass createFromJSON(JSONParcel source, ClassLoader loader) {

        }

        @Override
        public MyClass[] newArray(int size) {

        }
    }
}