How to Serialize/Deserialize Objects and Byte Arrays in Java
Given a serializable class, how can we convert the object state into a byte array byte[]?
Classes that can be serialized need to implement the interface Serializable. These classes are then eligible to be converted to and from a byte stream.
Suppose we have a serializable object called SerDeObject.
class SerDeObject implements Serializable { /* Attributes and methods*/ }
Serialization with ByteArrayOutputStream and try-with-resources
A clean way to convert an object into a byte array is to use the try-with-resources statement, which is a try statement that declares one or more resources.
A resource (i.e. ByteArrayOutputStream, ObjectOutputStream) is an object that must be closed after the program is finished with it.
We can declare the two resources in the try statement and use a combination of writeObject() and toByteArray() to convert an object to a byte array.
private byte[] objectToByteArray(SerDeObject object) throws IOException {
try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos)) {
out.writeObject(object);
out.flush();
return bos.toByteArray();
}
}
Similarly, we can define ByteArrayInputStream, ObjectInputStream, and use readObject() to convert a byte array to an object.
private SerDeObject byteArrayToObject(byte[] bytes) throws IOException, ClassNotFoundException {
try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInputStream in = new ObjectInputStream(bis)) {
return (SerDeObject) in.readObject();
}
}
Serialization with ByteArrayOutputStream and try-catch-finally
Note that the try-with-resources method only works with Java SE 7 and above. Prior to try-with-resources statements, we had to use a finally block to ensure that a resource is closed after a try or catch block.
Let’s serialize the object into a byte stream.
private byte[] objectToByteArray(SerDeObject object) throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out;
try {
out = new ObjectOutputStream(bos);
out.writeObject(object);
out.flush();
return bos.toByteArray();
} finally {
bos.close();
}
}
We can easily perform the opposite functionality as well.
private SerDeObject byteArrayToObject(byte[] bytes)
throws IOException, ClassNotFoundException {
ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
ObjectInput in = null;
try {
in = new ObjectInputStream(bis);
return (SerDeObject) in.readObject();
} finally {
if (in != null) {
in.close();
}
}
}
Serialization with SerializationUtils
We can also use SerializationUtils from Apache Commons Lang.
Converting to a byte array is super simple using serialize().
private byte[] objectToByteArray(SerDeObject object) {
return SerializationUtils.serialize(object);
}
Converting back to an object is just as easy using deserialize().
private SerDeObject byteArrayToObject(byte[] bytes) {
return SerializationUtils.deserialize(bytes);
}
Serialization with Jackson
We can also use Jackson’s writeValueAsBytes() to serialize an object as a byte array.
private byte[] objectToByteArray(SerDeObject object)
throws JsonProcessingException {
return new ObjectMapper().writeValueAsBytes(object);
}
We can deserialize using readValue().
private SerDeObject byteArrayToObject(byte[] bytes) throws IOException {
return new ObjectMapper().readValue(bytes, SerDeObject.class);
}