NancyFx/Nancy — pull request #1310 by logiclrd (2013-11-05 23:03:50+00:00)
Title: New type of converter to simplify representing byte[] as base64 strings

Good day :-) I've made a quick change that allows users to define what I've named "primitive converters" for JSON serialization/deserialization. These are like JavaScriptConverter classes, except the serialized side of the I/O is just an 'object', not an 'IDictionary'. These are then tied into the serialization process near the end of the pipeline, between object-level converters and actual translation of primitives and POD data to/from JSON text.

The reason I did this was because I really wanted to be able to use a 'byte[]' in my transport type, but have it serialize as a base64 string in the JSON to reduce size. My implementation of this, using the changes below, looks like this:

public class ByteArrayBase64Converter : JavaScriptPrimitiveConverter
{
public override object Deserialize(object primitiveValue, Type type, JavaScriptSerializer serializer)
{
if (primitiveValue == null)
return null;
else
return Convert.FromBase64String(primitiveValue.ToString());
}

public override object Serialize(object obj, JavaScriptSerializer serializer)
{
return Convert.ToBase64String((byte[])obj);
}

public override IEnumerable SupportedTypes
{
get { yield return typeof(byte[]); }
}
}

I also shortly thereafter found another use: I want to be able to return null models. (Perhaps there are very good reasons not to do this, and once I've learned them, I might not want to any more, but that's beside the point. :-) In initial testing, null models were working fine; the default JSON serialization produces the word 'null' as the entire body. Perfect. However, when I change my Accept header to "application/xml", I find that it is now making a dynamic call into the XML serializer into a generic method, and the null value is going into the field on which it normally infers the generic type. This causes an error. The main issue, of course, is that XML does not support any concept of null documents. This means that in order to be "like" null with XML, I need to create a type that serializes e.g. to "". However, this then causes the JSON output to be "{}" instead of "null".

Using a JavaScriptPrimitiveSerializer, I was able to make that Null class turn into a JSON 'null' while still satisfying XML serialization:

class NullObjectConverter : JavaScriptPrimitiveConverter
{
public override IEnumerable SupportedTypes
{
get { yield return typeof(NullObject); }
}

public override object Deserialize(object primitiveValue, Type type, JavaScriptSerializer serializer)
{
return null;
}

public override object Serialize(object obj, JavaScriptSerializer serializer)
{
return null;
}
}

I've done my best to follow local coding standards; in each document I edited, I preserved the local indentation and spacing to the best of my ability.