views:

110

answers:

5

There is a class I want to serialize, and it implements Serializable, but one of the objects it contains does not implement Serializable.

Is there a way to modify the class at runtime to make it implement the Serializable interface so I can serialize it? I can't change it at compile time because its a third party library.

Maybe I would have to use some sort of bytecode writer or something?

EDIT: Both the containing class and contained class are in the 3rd party library so I don't think i can mark something as transient. The containing class is marked as serializable, but it contains an object that is not.

I'm fine with writing a custom serialization method for the class, not sure how I would do this though, would I have to use reflection to get the values of the private variables?

+2  A: 

Fields can be skipped using the transient modifier. Additional data can be added to the stream by providing readObject and writeObject methods. Classes can be subclassed to make them serialisable (though you will need to manage the superclass data), or use a serial proxy (see Effective Java).

Tom Hawtin - tackline
+3  A: 

Reading the javadoc for Serializable, I see:

Classes that require special handling during the serialization and deserialization process must implement special methods with these exact signatures:

private void writeObject(java.io.ObjectOutputStream out)
     throws IOException
 private void readObject(java.io.ObjectInputStream in)
     throws IOException, ClassNotFoundException;
 private void readObjectNoData() 
     throws ObjectStreamException;

which you could use to manually serialize the uncooperative fields. You could look into using ASM, but it seems hard to believe that it is a maintainable solution.

bmargulies
Use Externalizable interface http://java.sun.com/j2se/1.3/docs/api/java/io/Externalizable.html
Gladwin Burboz
The containing class is also in the 3rd party library so I don't think I could add those methods to it.
Kyle
Then I guess it's time to learn asm.
bmargulies
A: 

If a class is not marked as Serializable that might be of good reasons (take database connections as an example). So first of all make your self clear if you really need to serialize that object as well. If you just need to serialize the surrounding object you may consider marking the contained object as transient.

Nils Schmidt
+1  A: 

First of all, do you really need to do this? Maybe the class in the third-party library is not serializable by design. Even if it's just an omission rather than a deliberate decision, it's easy enough to write a custom serialization method in a helper class. If you have to do this though (like I had to, for something similar). Take a look at Javassist. You can do something like this:

ClassPool pool = ClassPool.getDefault();
CtClass cc = pool.get("mypackage.MyClass");
cc.addInterface(pool.get("java.io.Serializable"))

EDIT: You can use a third-party Serialization API like XStream instead of doing all the dirty work yourself.

Chinmay Kanchi
About writing the custom serialization method in a helper class: How would I do this? Do I need to use reflection to get the private variable values?
Kyle
LOL. This answer is _already_ the third Google result for "serialization java third party" 32 minutes after the question was asked.
Chinmay Kanchi
A: 

You could use java.lang.reflect.Proxy to add the Serializable interface to object instances over which you have no life-cycle control (i.e. can't subcalass them) and get them serialized this way. But then you would still not be able to read them back without another hack (i.e. introducing a surrogate class).

I'd recommend to look for an alternative to the Java Serializable mechanism in general. It's pretty much broken by design in several ways.

x4u
It's strange that so many developers are completely fine with Java's "broken by design" Serialization. Rolling your own serialization is a horrible solution - so many standard Java libraries / frameworks make use of Serializable - are you supposed to program a workaround for every one of them?
Nate