简体   繁体   中英

How to serialize a java object with not Serializable fields inside it into byte array and deserialize the array to get the original object

Greetings to the community, I recently came up with an issue in serialization and deserialization in my java project. I have an object of a class containing other objects as fields .

I would like to store the state of the object into a byte array and then deserialize the byte array and get back the original object .However,the objects consisting my object's fields are not Serializable(came from third party library) so had to declare them as transient in first place.

Now my object is serialized and deserialized but as was to be expected it's fields are null because of the transient declaration i mentioned before.I have tried to create locally into my Serialization class all the elements and assign to them the original ones values and continue the process but it didnt had any difference. I quote below part of my code, Any ideas ? Thanks beforehand :)

Here is the class of my object with it's fields

public class AbePublicKey implements java.io.Serializable{

private static final long serialVersionUID = 7526472295622776147L;
public transient  Element g;
public transient Element h;
public transient Element f;
public transient Element e_g_g_hat_alpha;
}

Here is my Serializer function

 public  byte[] PublicKeytoByteArray(AbePublicKey publickey) throws IOException {

   KeyAuthority keyauthority = new KeyAuthority();
    byte[] bytes = null;
    ByteArrayOutputStream bos = null;
    ObjectOutputStream oos = null;
    publickey.setElements(g, h, f, e_g_g_hat_alpha);

    try {
        bos = new ByteArrayOutputStream();
        oos = new ObjectOutputStream(bos);
        oos.writeObject(publickey);
        oos.flush();
        bytes = bos.toByteArray();

    } finally {
        if (oos != null) 
            oos.close();
        }
        if (bos != null) {
            bos.close();
        }

    }

    return bytes;
}

Here is my Deserializer function

 public static AbePublicKey PublicKeyBytestoObject(byte[] publickeybytes) throws IOException, ClassNotFoundException {
    AbePublicKey obj = null;
    ByteArrayInputStream bis = null;
    ObjectInputStream ois = null;
    try {
        bis = new ByteArrayInputStream(publickeybytes);
        ois = new ObjectInputStream(bis);
        obj = (AbePublicKey) ois.readObject();

    } finally {
        if (bis != null) {
            bis.close();
        }
        if (ois != null) {
            ois.close();
        }
    }
    return obj;
}

If you want control over how an object is Serialized, implement the Externalizable interface and the associated readExternal and writeExternal methods. This gives you full control over how an object is serialized.

Clearly you can't serialize a class that contains fields that are not serializable. But you can perhaps write enough data to recreate the objects on your own.

If you are able to copy the values needed into new Serializable CustomElement objects inside your class, it should make a difference. Use copy constructors ( if available), or even reflection if you have enough information available.

You could wrap your Element fields in a class that is Serializable so that you can write them. This solution assumes you're able to call the necessary setters or constructor to recreate the Element after you read it.

Here is an example:

Very basic Element that is not Serializable

public class Element {

    private String value;

    public Element(){
        value = null;
    }

    public Element(String value){
        setValue(value);
    }

    public void setValue(String value){
        this.value = value;
    }

    public String getValue(){
        return value;
    }
}

Now a very basic wrapper class that is Serializable

import java.io.IOException;
import java.io.ObjectStreamException;
import java.io.Serializable;

public class SerializableElement implements Serializable{

    // Generated ID
    private static final long serialVersionUID = -6751688345227423403L;

    private transient Element element;

    public SerializableElement(Element el)
    {
        element = el;
    }

    private void writeObject(java.io.ObjectOutputStream out)
             throws IOException{
        out.writeObject(element.getValue());
    }
     private void readObject(java.io.ObjectInputStream in)
         throws IOException, ClassNotFoundException{
         String elementValue = (String)in.readObject();
         element = new Element(elementValue);
     }
     private void readObjectNoData()
         throws ObjectStreamException{
         element = null;
     }

     public Element getElement(){
         return element;
     }
}

Finally a main class to run the serializing and deserializing logic (slightly modified from what you posted) :

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class SerializeMain {

    public static void main(String[] args) {
        SerializableElement serializableElement = new SerializableElement(
                new Element("test value"));

        try {
            byte[] serializedData = storeElement(serializableElement);
            SerializableElement loadedElement = loadElement(serializedData);
            System.out.println("loadedElement.element.value: "
                    + loadedElement.getElement().getValue());

        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

    }

    public static byte[] storeElement(SerializableElement sElement)
            throws IOException {
        byte[] bytes = null;
        ByteArrayOutputStream bos = null;
        ObjectOutputStream oos = null;

        try {
            bos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(bos);
            oos.writeObject(sElement);
            oos.flush();
            bytes = bos.toByteArray();

        } finally {
            if (oos != null) {
                oos.close();
            }
            if (bos != null) {
                bos.close();
            }

        }

        return bytes;
    }

    public static SerializableElement loadElement(byte[] byteData)
            throws IOException, ClassNotFoundException {
        SerializableElement obj = null;
        ByteArrayInputStream bis = null;
        ObjectInputStream ois = null;
        try {
            bis = new ByteArrayInputStream(byteData);
            ois = new ObjectInputStream(bis);
            obj = (SerializableElement) ois.readObject();

        } finally {
            if (bis != null) {
                bis.close();
            }
            if (ois != null) {
                ois.close();
            }
        }
        return obj;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM