12

I am trying to serialize an ArrayList of JSONObjects. But I get the error:

05-07 01:04:24.130: WARN/System.err(913): java.io.NotSerializableException: org.json.JSONObject
05-07 01:04:24.130: WARN/System.err(913):     at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1535)
05-07 01:04:24.130: WARN/System.err(913):     at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
05-07 01:04:24.130: WARN/System.err(913):     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
05-07 01:04:24.130: WARN/System.err(913):     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
05-07 01:04:24.130: WARN/System.err(913):     at java.util.ArrayList.writeObject(ArrayList.java:651)
05-07 01:04:24.130: WARN/System.err(913):     at java.lang.reflect.Method.invokeNative(Native Method)
05-07 01:04:24.130: WARN/System.err(913):     at java.lang.reflect.Method.invoke(Method.java:507)
05-07 01:04:24.130: WARN/System.err(913):     at java.io.ObjectOutputStream.writeHierarchy(ObjectOutputStream.java:1219)
05-07 01:04:24.130: WARN/System.err(913):     at java.io.ObjectOutputStream.writeNewObject(ObjectOutputStream.java:1575)
05-07 01:04:24.130: WARN/System.err(913):     at java.io.ObjectOutputStream.writeObjectInternal(ObjectOutputStream.java:1847)
05-07 01:04:24.130: WARN/System.err(913):     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1689)
05-07 01:04:24.130: WARN/System.err(913):     at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:1653)
05-07 01:04:24.130: WARN/System.err(913):     at org.stocktwits.activity.AddStocksActivity.serializeQuotes(AddStocksActivity.java:183)
05-07 01:04:24.130: WARN/System.err(913):     at org.stocktwits.activity.AddStocksActivity.access$9(AddStocksActivity.java:178)
05-07 01:04:24.130: WARN/System.err(913):     at org.stocktwits.activity.AddStocksActivity$2.onItemClick(AddStocksActivity.java:146)
05-07 01:04:24.130: WARN/System.err(913):     at android.widget.AdapterView.performItemClick(AdapterView.java:284)
05-07 01:04:24.130: WARN/System.err(913):     at android.widget.ListView.performItemClick(ListView.java:3513)
05-07 01:04:24.130: WARN/System.err(913):     at android.widget.AbsListView$PerformClick.run(AbsListView.java:1812)
05-07 01:04:24.130: WARN/System.err(913):     at android.os.Handler.handleCallback(Handler.java:587)
05-07 01:04:24.130: WARN/System.err(913):     at android.os.Handler.dispatchMessage(Handler.java:92)
05-07 01:04:24.130: WARN/System.err(913):     at android.os.Looper.loop(Looper.java:130)
05-07 01:04:24.130: WARN/System.err(913):     at android.app.ActivityThread.main(ActivityThread.java:3683)
05-07 01:04:24.130: WARN/System.err(913):     at java.lang.reflect.Method.invokeNative(Native Method)
05-07 01:04:24.130: WARN/System.err(913):     at java.lang.reflect.Method.invoke(Method.java:507)
05-07 01:04:24.130: WARN/System.err(913):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
05-07 01:04:24.130: WARN/System.err(913):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
05-07 01:04:24.130: WARN/System.err(913):     at dalvik.system.NativeStart.main(Native Method)

Here is my serialize & deserialize code:

private void serializeQuotes() {
        FileOutputStream fos;
        try {
            fos = openFileOutput(Constants.FILENAME, Context.MODE_PRIVATE);
            ObjectOutputStream oos = new ObjectOutputStream(fos);
            oos.writeObject(quotes);
            oos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @SuppressWarnings("unchecked")
    private void deserializeQuotes() {
        try {
            FileInputStream fis = openFileInput(Constants.FILENAME);
            ObjectInputStream ois = new ObjectInputStream(fis);
            quotes = (ArrayList<JSONObject>) ois.readObject();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
Sheehan Alam
  • 60,111
  • 124
  • 355
  • 556

4 Answers4

50

Dude, it's JSON. Why not just serialize it as JSON, instead of as a Java object of type JSONObject?

For example:

String myJsonObjectSerialized = myJsonObject.toString();

Thane Anthem
  • 4,093
  • 4
  • 26
  • 24
  • Can you please elaborate? Maybe I'm just missing it completely - perhaps a small code example? – Sheehan Alam May 07 '11 at 00:24
  • Cool. The structure I'm storing is an ArrayList of JSONObjects. How would I go about doing that? – Sheehan Alam May 07 '11 at 00:58
  • @Sheehan Alam - either put the JSONObjects into a JSONArray, or use a for loop. – Stephen C May 07 '11 at 01:04
  • Another scenario would be a HashMap with a JSONObject like in this question: http://stackoverflow.com/questions/3818745/androidruntime-error-parcel-unable-to-marshal-value (replace `Bottle` with `JSONObject`) – nuala Jul 29 '13 at 14:24
  • 1
    Just stumbled across this issue. Not implementing Serializable on a class that is used for serialization is... an interesting decision to say the least. It's not like it would break anything at all or am I missing something here? – domenukk Nov 06 '16 at 02:00
  • @ThaneAnthem How can I put and get this JSONObject inside the in-memory cache like Memcached? – Jinu P C Jan 10 '18 at 09:49
  • When using `toString()`, `Date` objects will be converted to string. So when converting the string back to JSONObject, it'll not be the same! – Jan Gassen Oct 11 '18 at 11:33
  • @ThaneAnthem What if my db type is jsonb? It has to be type-casted to persist – Varshney P. Nov 08 '19 at 11:05
15

In the case you'd still want Java built-in serialization without having to resort to marshal your JSON object into string notation, one thing you could do is extend JSONObject and JSONArray from org.json and just implement Serializable.

Then you can use your own versions of JSONObject and JSONArray across the board instead of the originals.

Make sure you define all constructors on your subclasses and call their super() counterparts as well as implement specific methods that return the parent types such as getJSONObject() and getJSONArray() from properties.

Roberto Andrade
  • 1,793
  • 1
  • 21
  • 27
  • 3
    voting up, since this is the right approach. I do the same since I am caching a comples JSONObject on MemCache, rather than get it created all the time or stringified. – gextra Apr 26 '13 at 12:48
  • 2
    This does seem to work, but is it "safe" to do? Something about extending a 3rd party class that isn't serializable, and then marking it as so, seems a little risky. – chinabuffet Oct 05 '16 at 13:13
  • 1
    This is a better approach than the accepted one! – MiniScalope Jan 06 '22 at 17:52
3

Another way is to swap org.json library with json-simple.

The JSONObject class from json-simple extends HashMap which is java Serializable as well as more java-ish API.

Maven dependency:

http://mvnrepository.com/artifact/com.googlecode.json-simple/json-simple/1.1.1

Example usage:

https://www.mkyong.com/java/json-simple-example-read-and-write-json/

Community
  • 1
  • 1
Thamme Gowda
  • 11,249
  • 5
  • 50
  • 57
2

If you have JSONArray inside Serializable object class try to initialize JSONArray in this way.

private transient JSONArray jsonArray;

public class Person implements Serializable {   

     private String name;  
     private transient JSONArray jsonArray;

     public String getName() {  
          return name;  
     }  

    public void setName(String name) {  
          this.name = name;  
     }

    public JSONArray getJsonArray() {  
          return jsonArray;  
     }  

    public void setJsonArray(JSONArray jsonArray) {  
          this.jsonArray = jsonArray;  
     }  

 }
Mani
  • 3,394
  • 3
  • 30
  • 36