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
ObjectOutputStream
from aByteArrayOutputStream
- Serialize to
Object
callingwriteObject()
on theObjectOutputStream
- Construct a
String
from 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(); } } }