I have a strange problem in my Android code when I try to pass json-smart JSONObject or JSONArray as a serializable data as Intent serializable extra. Json-smart is very fast and lean JSON parser implementation, I highly recommend it. JSONObject extends HashMap<String, Object> and JSONArray extends ArrayList<Object> with very little overhead. Nether of these objects override Object#write or Object#read
Here’s the problem:
If I use these objects in say Fragment#onSaveInstanceState(String, JSONObject) everything works just fine. If I serialize/deserialize these objects in plain Java sample project, again it works as intended. However if I use Intent#putExtra(String, JSONObject) and then try to get my JSONObject by doing
JSONObject json = (JSONObject) intent.getSerializableExtra("JSON");
I will get ClassCastException because what is returned by the method is a plain HashMap (and in case of JSONArray it’s ArrayList). Moreover if I look inside the map/array the content is completely stripped of any references to JSONObject/JSONArray and replaced with HashMaps/ArrayLists
I filed the ticket and provided example project but unfortunately author closed it without resolution, so I’m simply trying to get to the bottom of it. If you go to the ticket it has simple project attached.
Is there a way out of this? For now I have to convert JSONObject or JSONArray to String and reparse it back to the object such as in:
JSONArray feeds = (JSONArray) JSONValue.parse(intent.getStringExtra(RAW_FEED));
Implement android.os.Parcelable:
Basically, you put a little extra code into your object to explain how to serialize and deserialize it. That’s why it’s losing your class information, it doesn’t know how to serialize it correctly. If I were you I would pass a value object through your intent verses a JSON object simply because know you know exactly what type of object you are passing. You retrieve your Parcelable this way:
I know it probably seems like a little extra code but I actually think this is a pretty clean way to share data between activities. You are passing a strong type, you specify how to deflate/inflate it, and your activities don’t really have to have any working knowledge of each other.
In your value object you just fill in the blanks like this:
Hope this helps, might be little more code than what you were looking for but it’s a real clean solution because when the target activity gets the object, you don’t have to worry about deserializing which means cleaner code in your activity. Fat model, clean views 🙂