3

How can I implement serialization on my own. Meaning I don't want my class to implement serializable. But I want to implement serialization myself. So that without implementing serializable I can transfer objects over network or write them to a file and later retrieve them in same state. I want to do it since I want to learn and explore things.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
akshay
  • 365
  • 2
  • 5
  • 9
  • 1
    What have you tried? Is there a specific issue we can help with? This is extremely difficult to implement, and discussing how to do it is so complicated that you're almost better off reading the Java Language Specification to see how it's done. – templatetypedef Feb 08 '11 at 04:42

5 Answers5

6

Serialization is the process of translating the structure of an object into another format that could be easily transfered across network or could be stored in a file. Java serializes objects into a binary format. This is not necessary if bandwidth/disk-space is not a problem. You can simply encode your objects as XML:

// Code is for illustration purpose only, I haven't compiled it!!!

public class Person {
    private String name;
    private int age;
    // ...

   public String serializeToXml() {
       StringBuilder xml = new StringBuilder();   
       xml.append("<person>");
       xml.append("<attribute name=\"age\" type=\"int\">").append(age);
       xml.append("</attribute>");
       xml.append("<attribute name=\"name\" type=\"string\">").append(name);
       xml.append("</attribute>"); 
       xml.append("</person>");
       return xml.toString(); 
}

Now you can get an object's XML representation and "serialize" it to a file or a network connection. A program written in any language that can parse XML can "deserialize" this object into its own data structure.

If you need a more compact representation, you can think of binary encoding:

  // A naive binary serializer. 
  public byte[] serializeToBytes() {
      ByteArrayOutputStream bytes = new ByteArrayOutputStream(); 

      // Object name and number of attributes.
      // Write the 4 byte length of the string and the string itself to
      // the ByteArrayOutputStream.
      writeString("Person", bytes);
      bytes.write(2); // number of attributes;

      // Serialize age
      writeString("age", bytes);
      bytes.write(1); // type = 1 (i.e, int)
      writeString(Integer.toString(age), bytes);  

      // serialize name
      writeString("name", bytes);
      bytes.write(2); // type = 2 (i.e, string) 
      writeString(name, bytes);

      return bytes.toByteArray();
  }

  private static void writeString(String s, ByteArrayOutputStream bytes) {
      bytes.write(s.length());
      bytes.write(s.toBytes());
  }

To learn about a more compact binary serialization scheme, see the Java implementation of Google Protocol Buffers.

Pang
  • 9,564
  • 146
  • 81
  • 122
Vijay Mathew
  • 26,737
  • 4
  • 62
  • 93
1

You can use Externalizable and implement your own serialization mechanism. One of the difficult aspects of serialization is versioning so this can be a challenging exercise to implement. You can also look at protobuf and Avro as binary serialization formats.

Community
  • 1
  • 1
Aravind Yarram
  • 78,777
  • 46
  • 231
  • 327
1

You start with reflection. Get the object's class and declared fields of its class and all superclasses. Then obtain value of each field and write it to dump.

When deserializing, just reverse the process: get class name from your serialized form, instantiate an object and set its fields accordingly to the dump.

That's the simplistic approach if you just want to learn. There's many issues that can come up if you want to do it "for real":

  • Versioning. What if one end of the application is running new version, but the other end has an older class definition with some fields missing or renamed?
  • Overwriting default behavior. What if some object is more complex and cannot be recreated on a simple field-by-field basis?
  • Recreating dependencies between objects, including cyclic ones.
  • ... and probably many more.
Konrad Garus
  • 53,145
  • 43
  • 157
  • 230
0

Get the Java Source code and understand how Serialization is implemented. I did this some month ago, and now have a Serialization that uses only 16% of the space and 20% of the time of "normal" serialization, at the cost of assuming that the classes that wrote the serialized data have not changed. I use this for client-server serialization where I can use this assumption.

Daniel
  • 27,718
  • 20
  • 89
  • 133
0

As a supplement to @Konrad Garus' answer. There is one issue that is a show-stopper for a full reimplementation of Java serialization.

When you deserialize an object, you need to use one of the object's class's constructors to recreate an instance. But which constructor should you use? If there is a no-args constructor, you could conceivably use that. However, the no-args constructor (or indeed any constructor) might do something with the object in addition to creating it. For example, it might send a notification to something else that a new instance has been created ... passing the instance that isn't yet completely deserialized.

In fact, it is really difficult replicate what standard Java deserialization code does. What it does is this:

  1. It determines the class to be created.
  2. Create an instance of the class without calling any of its constructors.
  3. It uses reflection to fill in the instance's fields, including private fields, with objects and values reconstructed from the serialization.

The problem is that step 2. involves some "black magic" that a normal Java class is not permitted to do.

(If you want to understand the gory details, read the serialization spec and take a look at the implementation in the OpenJDK codebase.)

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216