{8.1.0-updated} PojoSwaps

{@link oaj.transform.PojoSwap PojoSwaps} are a critical component of Juneau. They allow the serializers and parsers to handle Java objects that wouldn't normally be serializable.

Swaps are, simply put, 'object swappers' that swap in serializable objects for non-serializable ones during serialization, and vis-versa during parsing.

Some examples of non-serializable POJOs are File, Reader, Iterable, etc... These are classes that aren't beans and cannot be represented as simple maps, collections, or primitives.

In the following example, we introduce a PojoSwap that will swap in a bean of a particular type with a map containing customized key-value pairs:

// Sample swap for converting a bean to a specialized map of key-value pairs. public class MyBeanSwap extends PojoSwap<MyBean,ObjectMap> { // Converts a bean to a generic map. @Override /* PojoSwap */ public ObjectMap swap(BeanSession session, MyBean o) { return new ObjectMap().append("foo", o.getBar()); } // Converts the generic map back into a bean. @Override /* PojoSwap */ public MyBean unswap(BeanSession session, ObjectMap o, ClassMeta hint) throws Exception { MyBean b = new MyBean(); b.setBar(o.getString("foo")); return b; } }

The swap can then be associated with serializers and parsers like so:

// Create a new JSON serializer with our swap. WriterSerializer s = JsonSerializer.create().simple().pojoSwaps(MyBeanSwap.class).build(); String json = s.serialize(new MyBean()); // Create a JSON parser with our swap. ReaderParser p = JsonParser.create().pojoSwaps(MyBeanSwap.class).build(); MyBean bean = p.parse(json, MyBean.class);

Another example of a PojoSwap is one that converts byte[] arrays to BASE64-encoded strings:

public class ByteArrayBase64Swap extends StringSwap<byte[]> { @Override /* StringSwap */ public String swap(byte[] b) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); OutputStream b64os = MimeUtility.encode(baos, "base64"); b64os.write(b); b64os.close(); return new String(baos.toByteArray()); } @Override /* StringSwap */ public byte[] unswap(String s, ClassMeta<?> hint) throws Exception { byte[] b = s.getBytes(); ByteArrayInputStream bais = new ByteArrayInputStream(b); InputStream b64is = MimeUtility.decode(bais, "base64"); byte[] tmp = new byte[b.length]; int n = b64is.read(tmp); byte[] res = new byte[n]; System.arraycopy(tmp, 0, res, 0, n); return res; } }

The following example shows the BASE64 swap in use:

// Create a JSON serializer and register the BASE64 encoding swap with it. WriterSerializer s = JsonSerializer.create().simple().pojoSwaps(ByteArrayBase64Swap.class).build(); ReaderParser p = JsonParser.create().pojoSwaps(ByteArrayBase64Swap.class).build(); byte[] bytes = {1,2,3}; String json = s.serialize(bytes); // Produces "'AQID'" bytes = p.parse(json, byte[].class); // Reproduces {1,2,3} byte[][] bytes2d = {{1,2,3},{4,5,6},null}; json = s.serialize(bytes2d); // Produces "['AQID','BAUG',null]" bytes2d = p.parse(json, byte[][].class); // Reproduces {{1,2,3},{4,5,6},null}