A writeable basically needs to implement two methods:
/**
* Serialize the fields of this object to <code>out</code>.
*
* @param out <code>DataOuput</code> to serialize this object into.
* @throws IOException
*/
void write(DataOutput out) throws IOException;
/**
* Deserialize the fields of this object from <code>in</code>.
*
* <p>For efficiency, implementations should attempt to re-use storage in
the
* existing object where possible.</p>
*
* @param in <code>DataInput</code> to deseriablize this object from.
* @throws IOException
*/
void readFields(DataInput in) throws IOException;
These use the serialization primitives to pack and unpack the object.
These are from the hadoop Text class in 0.19.1
/** deserialize
*/
public void readFields(DataInput in) throws IOException {
int newLength = WritableUtils.readVInt(in);
setCapacity(newLength, false);
in.readFully(bytes, 0, newLength);
length = newLength;
}
/** serialize
* write this object to out
* length uses zero-compressed encoding
* @see Writable#write(DataOutput)
*/
public void write(DataOutput out) throws IOException {
WritableUtils.writeVInt(out, length);
out.write(bytes, 0, length);
}
If you look at the various implementors of Writable, you will find plenty of
examples in the source tree.
For very complex objects, the simplest thing to do is to serialize them to
an ObjectOutputStream that is backed by a ByteArrayOutputStream then use the
write/read byte array method on the DataOutput/DataInput
In my code I check to see if in/out implement the the ObjectXXXXXStream and
use it directly, or use an intermediate byte array.