In Core J2EE Design Patterns 2nd edition, I saw a small hack that I wasn’t aware of. You can serialize/deserialize any Serializable object to/from a String. I saw this in the Service Locator design pattern where it is used to serialize/deserialize javax.ejb.Handle objects (pages 332-333).
The above serialization is very easy to implement. All you need is to:
- Construct an
ObjectOutputStreamfrom aByteArrayOutputStream - Serialize to
ObjectcallingwriteObject()on theObjectOutputStream - Construct a
Stringfrom the bytes of theByteArrayOutputStream
Below I have implemented, in Java 5, a class that serializes/deserializes any Serializable object to/from a String object.
import java.io.*;
public class ToStringSerializer<T extends Serializable> {
public String serialize(T t) throws IOException {
ByteArrayOutputStream bs = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bs);
os.writeObject(t);
return new String(bs.toByteArray());
}
public T fromString(String s) throws IOException, ClassNotFoundException {
ByteArrayInputStream bs = new ByteArrayInputStream(s.getBytes());
ObjectInputStream os = new ObjectInputStream(bs);
return (T) os.readObject();
}
}
A minimal unit test to demonstrate the usage of the above class:
import java.io.Serializable;
import junit.framework.TestCase;
public class ToStringSerializerTest extends TestCase {
public final void testSerialize() throws Exception {
Pair<String , String> p = new Pair<String, String>("Fist", "Second");
ToStringSerializer<Pair<String, String>> serializer =
new ToStringSerializer<Pair<String, String>>();
String pAsString = serializer.serialize(p);
Pair<String, String> newP = serializer.fromString(pAsString);
assertEquals(p, newP);
}
static class Pair<F, S> implements Serializable {
private F first;
private S second;
public Pair(F f, S s) { first = f; second = s; }
public Pair() {}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Pair)) return false;
Pair, ?> p = (Pair, ?>) obj;
return first.equals(p.first) && second.equals(p.second);
}
@Override
public int hashCode() {
return 71*first.hashCode() + second.hashCode();
}
}
}