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);
}