Making XMLEncoder do something sensible with binary data

By default, XMLEncoder encodes byte arrays like any other array:

   <array class="byte" length="8">
    <void index="0">
    <void index="1">

Repeat for every byte. This is bad.

A reasonable solution would be to store the whole byte array as a base 64 encoded string. Here’s how (it took a bit of figuring out):

public class ByteArrayPersistenceDelegate extends PersistenceDelegate {
    protected Expression instantiate(Object oldInstance, Encoder out) {
        byte[] e = (byte[]) oldInstance;
        return new Expression(e, ByteArrayPersistenceDelegate.class, "decode",
                new Object[]{ByteArrayPersistenceDelegate.encode(e)});

// We want methods from this class to appear in the data - the indirection means we're
    // not tied to a particular Base64 implementation and are protected from interface changes.

public static byte[] decode(String encoded) {
        return org.apache.commons.codec.binary.Base64.decodeBase64(encoded);

public static String encode(byte[] data) {
        return org.apache.commons.codec.binary.Base64.encodeBase64String(data);


XMLEncoder e = new XMLEncoder(out) {
    public PersistenceDelegate getPersistenceDelegate(Class<?> type) {
        if (type == byte[].class)
            return del;
            return super.getPersistenceDelegate(type);

See how you actually have to override getPersistenceDelegate()? You might think you’d setPersistenceDelegate() for byte[], but that doesn’t work – you still end up with the default array delegate and the default output.

That Base64 class is from the Commons Codec library, by the way.

Comments are closed.