Java Serializable Object to Byte Array
Asked Answered
G

13

333

Let's say I have a serializable class AppMessage.

I would like to transmit it as byte[] over sockets to another machine where it is rebuilt from the bytes received.

How could I achieve this?

Gabriellia answered 14/5, 2010 at 18:31 Comment(3)
Why as byte[]? Why not just write it directly to the socket with ObjectOutputStream, and read it with ObjectInputStream?Scoff
use apache camelCapitulation
new ObjectMapper().writeValueAsBytes(JAVA_OBJECT_HERE)Orthogonal
A
460

Prepare the byte array to send:

static byte[] serialize(final Object obj) {
    ByteArrayOutputStream bos = new ByteArrayOutputStream();

    try (ObjectOutputStream out = new ObjectOutputStream(bos)) {
        out.writeObject(obj);
        out.flush();
        return bos.toByteArray();
    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }
}

Create an object from a byte array:

static Object deserialize(byte[] bytes) {
    ByteArrayInputStream bis = new ByteArrayInputStream(bytes);

    try (ObjectInput in = new ObjectInputStream(bis)) {
        return in.readObject();
    } catch (Exception ex) {
        throw new RuntimeException(ex);
    }
}
Adulterer answered 14/5, 2010 at 18:33 Comment(12)
That's not how I read the question. To me it sounds like his problem is how to convert the object to a byte[] -- not how to send it.Adulterer
Taylor: yes you got it right. i want to turn the object into a byte[] and transmit it. can you please also provide the code regarding how to turn this byte[] into an object please?Gabriellia
Please close always any stream to release the system resources. (Edited in code)Lex
can this work with objects that I can't implement serializable?Ethanethane
how do you deal with the uncaught exceptions on the statements in the "finally" block?Glioma
thank you so much. this works great sending a custom Settings object (with loads of settings) from android phone to android watch as a byte[]Soup
The original closed out but it was edited away. See stackoverflow.com/posts/2836659/revisions.Adulterer
ObjectInput, ObjectOuput, ByteArrayOutputStream and ByteArrayInputStream all implement the AutoCloseable interface, wouldn't it be good practice to use it to avoid missing closing them by mistake? (I'm not entirely sure if this is the best practice, that's why I'm wondering.) Example: try(ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutput out = new ObjectOutputStream(bos)){ /*Do stuff*/ }catch(IOException e){/*suppress exception*/}. It also removes the need for the final clause and its additional try-catch.Lemieux
@LudvigRydahl: answer comes from 2010, Java7 (and try-with-resource) comes from 2011. Otherwise yes, try-with-resource is a good practice - however, that does not apply to the "suppress" part, which is a bad practice.Firdausi
@Firdausi that is true about Java 7.however I only posted suppress,which in most cases is a terrible handling, since the answer said ignore.Lemieux
@LudvigRydahl: Note that the answer ignores exception from resource.close() only. Using try-with-resource, you just close the block and you have the same thing as in the answer (there is no catch in it either, only the finally)Firdausi
@Esko There is nothing in the question about RMI or obect construction and deconstruction whatsoever, and this answer covers both serialization and serialization mechanisms.Scoff
I
343

The best way to do it is to use SerializationUtils from Apache Commons Lang.

To serialize:

byte[] data = SerializationUtils.serialize(yourObject);

To deserialize:

YourObject yourObject = SerializationUtils.deserialize(data)

As mentioned, this requires Commons Lang library. It can be imported using Gradle:

compile 'org.apache.commons:commons-lang3:3.5'

Maven:

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.5</version>
</dependency>

Jar file

And more ways mentioned here

Alternatively, the whole collection can be imported. Refer this link

Identic answered 1/11, 2012 at 10:17 Comment(9)
Added overhead? Might as well rebuild the wheel at this point. Seriously, it's much more easy to understand this one-liner and reduce possible errors (like not closing the stream at right time and whatnot).Urethra
Best way because you use a common library offering you: 1) Robustness: People are using this and thus it is validated to work. 2) It does the above (most popular answer) with only 1 line so your code stays clean. 3) Because Dan said so. 4) I'm just kidding regarding to 3 :-)Trauma
Unfortunately, the method restricts the output size to 1024. If one needs to convert a file to a byte stream, better not use this.Ephrayim
I would not prefer this one for microservices. The library could make them heavier is size, than direct methods.Nephrectomy
to use SerializationUtils.serialize(o), your object need this implements SerializableOmnipresent
@zon so the accepted answer is better than this method if we want to keep the size of the application small?Malayoindonesian
@Malayoindonesian The accepted answer is a bit outdated. Romero's one is neater as it uses try-with-resources.Nephrectomy
@Ephrayim 1024 is the initial size and the limit doesn't apply as gzg confirmed here https://mcmap.net/q/98323/-java-serializable-object-to-byte-array and I verified the source code as wellWove
Be careful of certain versions of Apache Commons's (de)serialization library if you are trying to sandbox the application! There are known vulnerabilities regarding custom deserialization methods. Use a SecurityManager or update to the newest Apache Commons versionLenny
S
103

If you use Java >= 7, you could improve the accepted solution using try with resources:

private byte[] convertToBytes(Object object) throws IOException {
    try (ByteArrayOutputStream bos = new ByteArrayOutputStream();
         ObjectOutputStream out = new ObjectOutputStream(bos)) {
        out.writeObject(object);
        return bos.toByteArray();
    } 
}

And the other way around:

private Object convertFromBytes(byte[] bytes) throws IOException, ClassNotFoundException {
    try (ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
         ObjectInputStream in = new ObjectInputStream(bis)) {
        return in.readObject();
    } 
}
Sequin answered 21/6, 2015 at 20:7 Comment(1)
It is not quite the same than the accepted solution as the written data is not flushed before method toByteArray() is invoked, i.e. it could happen that some data remains in internal buffers and that not all data is transferred to the returned byte[] array. I have not found a specification of the ObjectOutputStream which describe buffer behavior.Bissau
A
14

Can be done by SerializationUtils, by serialize & deserialize method by ApacheUtils to convert object to byte[] and vice-versa , as stated in @uris answer.

To convert an object to byte[] by serializing:

byte[] data = SerializationUtils.serialize(object);

To convert byte[] to object by deserializing::

Object object = (Object) SerializationUtils.deserialize(byte[] data)

Click on the link to Download org-apache-commons-lang.jar

Integrate .jar file by clicking:

FileName -> Open Medule Settings -> Select your module -> Dependencies -> Add Jar file and you are done.

Hope this helps.

Ambulatory answered 22/4, 2017 at 5:1 Comment(1)
never add a dependency like this, use maven/gradle to download dependency and add it to the build pathSundew
O
7

Another interesting method is from com.fasterxml.jackson.databind.ObjectMapper

byte[] data = new ObjectMapper().writeValueAsBytes(JAVA_OBJECT_HERE)

Maven Dependency

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
</dependency>
Orthogonal answered 12/9, 2019 at 8:6 Comment(0)
S
6

I also recommend to use SerializationUtils tool. I want to make a ajust on a wrong comment by @Abilash. The SerializationUtils.serialize() method is not restricted to 1024 bytes, contrary to another answer here.

public static byte[] serialize(Object object) {
    if (object == null) {
        return null;
    }
    ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
    try {
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(object);
        oos.flush();
    }
    catch (IOException ex) {
        throw new IllegalArgumentException("Failed to serialize object of type: " + object.getClass(), ex);
    }
    return baos.toByteArray();
}

At first sight, you may think that new ByteArrayOutputStream(1024) will only allow a fixed size. But if you take a close look at the ByteArrayOutputStream, you will figure out the the stream will grow if necessary:

This class implements an output stream in which the data is written into a byte array. The buffer automatically grows as data is written to it. The data can be retrieved using toByteArray() and toString().

Scanty answered 15/5, 2018 at 7:6 Comment(2)
can you add how to do the reverse? so byte[] to object? I know others have this, but I like your answer a lot more and I can't get the deserialisation to work. I want to avoid returning null in any case.Frivolity
I was also skeptical about this code after reading @Ephrayim answer. But you cleared me. Thanks.Whaling
N
5

If you are using spring, there's a util class available in spring-core. You can simply do

import org.springframework.util.SerializationUtils;

byte[] bytes = SerializationUtils.serialize(anyObject);
Object object = SerializationUtils.deserialize(bytes);
Nepali answered 20/1, 2020 at 8:22 Comment(1)
@PaleBlueDot yes it is, if you go to the method and see the implementation, you could see that it doesn't involve any global member.Nepali
S
1

I would like to transmit it as byte[] over sockets to another machine

// When you connect
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
// When you want to send it
oos.writeObject(appMessage);

where it is rebuilt from the bytes received.

// When you connect
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
// When you want to receive it
AppMessage appMessage = (AppMessage)ois.readObject();
Scoff answered 15/5, 2018 at 7:20 Comment(0)
W
1

Spring Framework org.springframework.util.SerializationUtils

byte[] data = SerializationUtils.serialize(obj);
Waldenburg answered 30/9, 2019 at 11:41 Comment(0)
O
1

In case you want a nice no dependencies copy-paste solution. Grab the code below.

Example

MyObject myObject = ...

byte[] bytes = SerializeUtils.serialize(myObject);
myObject = SerializeUtils.deserialize(bytes);

Source

import java.io.*;

public class SerializeUtils {

    public static byte[] serialize(Serializable value) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();

        try(ObjectOutputStream outputStream = new ObjectOutputStream(out)) {
            outputStream.writeObject(value);
        }

        return out.toByteArray();
    }

    public static <T extends Serializable> T deserialize(byte[] data) throws IOException, ClassNotFoundException {
        try(ByteArrayInputStream bis = new ByteArrayInputStream(data)) {
            //noinspection unchecked
            return (T) new ObjectInputStream(bis).readObject();
        }
    }
}
Olivero answered 5/5, 2020 at 3:50 Comment(0)
B
0

This is just an optimized code form of the accepted answer in case anyone wants to use this in production :

    public static void byteArrayOps() throws IOException, ClassNotFoundException{

    String str="123";
     byte[] yourBytes = null;

    // Convert to byte[]

    try(ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream out =  new ObjectOutputStream(bos);) {


      out.writeObject(str);
      out.flush();
      yourBytes = bos.toByteArray();

    } finally {

    }

    // convert back to Object

    try(ByteArrayInputStream bis = new ByteArrayInputStream(yourBytes);
            ObjectInput in = new ObjectInputStream(bis);) {

      Object o = in.readObject(); 

    } finally {

    }




}
Borodin answered 2/6, 2020 at 0:5 Comment(0)
A
0

make sure to implements Serializable or exception will be your destiny

public class Dto implements Serializable {


private String firstName;
private String lastName;
private Integer myNumber;
public String getFirstName() {
    return firstName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

public String getLastName() {
    return lastName;
}

public void setLastName(String lastName) {
    this.lastName = lastName;
}

public Integer getMyNumber() {
    return myNumber;
}

public void setMyNumber(Integer myNumber) {
    this.myNumber = myNumber;
}

@Override
public String toString() {
    return "Dto{" +
            "firstName='" + firstName + '\'' +
            ", lastName='" + lastName + '\'' +
            ", myNumber=" + myNumber +
            '}';
}

}

public class Main {
public static void main(String[] args) {
    Dto dto=new Dto();
    dto.setFirstName("Sajjad");
    dto.setLastName("ahmed");
    dto.setMyNumber(0305);


    byte[] serializedDto = serializeObject(dto);


    System.out.println("Serialized Dto=== " + new String(serializedDto));


    Dto deserializedDto = deserializeObject(serializedDto);


    System.out.println("Deserialized Dto===" + deserializedDto);




}



private static byte[] serializeObject(Dto dto) {
    try {
        ByteArrayOutputStream byteOutputStream = new ByteArrayOutputStream();
        ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteOutputStream);


        objectOutputStream.writeObject(dto);


        objectOutputStream.close();
        byteOutputStream.close();


        return byteOutputStream.toByteArray();

    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }}
    private static Dto deserializeObject(byte[] byteArray) {
        try {

            ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray);
            ObjectInputStream objectInputStream = new ObjectInputStream(byteInputStream);


            Dto deserializedObject = (Dto) objectInputStream.readObject();


            objectInputStream.close();
            byteInputStream.close();

            return deserializedObject;

        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
            return null;
        }
    }

}

Asta answered 8/12, 2023 at 7:45 Comment(0)
J
-1

code example with java 8+:

public class Person implements Serializable {

private String lastName;
private String firstName;

public Person() {
}

public Person(String firstName, String lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
}

public void setFirstName(String firstName) {
    this.firstName = firstName;
}

public String getFirstName() {
    return firstName;
}

public String getLastName() {
    return lastName;
}

public void setLastName(String lastName) {
    this.lastName = lastName;
}

@Override
public String toString() {
    return "firstName: " + firstName + ", lastName: " + lastName;
}
}


public interface PersonMarshaller {
default Person fromStream(InputStream inputStream) {
    try (ObjectInputStream objectInputStream = new ObjectInputStream(inputStream)) {
        Person person= (Person) objectInputStream.readObject();
        return person;
    } catch (IOException | ClassNotFoundException e) {
        System.err.println(e.getMessage());
        return null;
    }
}

default OutputStream toStream(Person person) {
    try (OutputStream outputStream = new ByteArrayOutputStream()) {
        ObjectOutput objectOutput = new ObjectOutputStream(outputStream);
        objectOutput.writeObject(person);
        objectOutput.flush();
        return outputStream;
    } catch (IOException e) {
        System.err.println(e.getMessage());
        return null;
    }

}

}
Jolley answered 1/3, 2019 at 20:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.