4

I would like to serialize all my contract with $type reference using TypeNameHandling.Objects. However when using this flag, all byte arrays (byte[]) are serialized using $value+$type. I still want Base64 encoding but without $type. For example, for the following contract:

class MyClass
{
  public byte[] MyBinaryProperty {get;set;}
}

I get:

{
  "$type": "MyLib.MyClass, MyAssembly",
  "MyBinaryProperty": {
    "$type": "System.Byte[], mscorlib",
    "$value": "VGVzdGluZw=="
  }
}

I want:

{
  "$type": "MyLib.MyClass, MyAssembly",
  "MyBinaryProperty": "VGVzdGluZw=="
}

Is it possible to serialize all objects via JSON.NET with $type excluding byte arrays? Can I do this without adding any attributes to the contracts (i.e. I want to only alter serializer settings).

3
  • @Hexxagonal: That's not what the OP is asking Commented Jun 12, 2015 at 19:22
  • maybe json wants to let you know it's a byte[] defined in mscorlib. not sure Commented Jun 12, 2015 at 19:24
  • @Hexxagonal: This is not a duplicate of that question. Commented Jun 12, 2015 at 19:29

1 Answer 1

4

One way to fix this would be to use a custom converter for byte[]:

public class ByteArrayConverter : JsonConverter
{
    public override object ReadJson(
        JsonReader reader,
        Type objectType,
        object existingValue,
        JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(
        JsonWriter writer,
        object value,
        JsonSerializer serializer)
    {
        string base64String = Convert.ToBase64String((byte[])value);

        serializer.Serialize(writer, base64String);
    }    

    public override bool CanRead
    {
        get { return false; }
    }

    public override bool CanConvert(Type t)
    {
        return typeof(byte[]).IsAssignableFrom(t);
    }
}

This way you're overriding how byte[] gets serialized and ultimately passing the serializer a string instead of a byte array.

Here's how you'd use it:

string serialized = JsonConvert.SerializeObject(mc, new JsonSerializerSettings
{
    TypeNameHandling = TypeNameHandling.Objects,
    Formatting = Newtonsoft.Json.Formatting.Indented,
    Converters = new[] { new ByteArrayConverter() }
});

Example output:

{
  "$type": "UserQuery+MyClass, query_fajhpy",
  "MyBinaryProperty": "AQIDBA=="
}

Example: https://dotnetfiddle.net/iDEPIT

Sign up to request clarification or add additional context in comments.

1 Comment

That was quick! I must admit I am gobsmacked... very clever. It does work beautifully.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.