How to Serialize/Deserialize Objects and Byte Arrays in Java

Published Apr 30, 2022  ∙  Updated May 2, 2022

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