Question

Hopefully this is an easy fix that I have overlooked. I have an object passed into an event handler that I want to serialize that object using JSON.NET, like so:

public void OnEvent(IEventObject foo)
{
    // Serialize foo to string/disk here?
    var data = JsonConvert.SerializeObject(foo, Formatting.Indented);
}

It appears that one or more of foo's members are streams. I already recognize that Streams are not serializable since they are an abstraction over data and not the data itself. This makes sense.

I do not know how to serialize this object anyway by either:

  • a) Converting the streams into data and serializing that
  • b) Ignoring the streams and serialize the remaining members

One big caveat to this is that I do not have access to IEventObject or its implementations, so I cannot mark up any of these objects with attribute flags.

The only solution I have come up with is to wrap this object in my own class, mark it up appropriately, and serialize that. Later I would deserialize back into my own class, and convert it into the original object. I don't like this approach since it involves an extra object and conversion step, and would like to avoid it if possible.

Was it helpful?

Solution

By default, Json.NET will try to serialize the properties of the stream, which isn't very useful. You can modify the behavior by creating your own contract resolver. Here's an example that ignores all Streams entirely:

public class IgnoreStreamsResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(
        MemberInfo member,
        MemberSerialization memberSerialization
    )
    {
        JsonProperty property = base.CreateProperty(member, memberSerialization);
        if (typeof(Stream).IsAssignableFrom(property.PropertyType))
        {
            property.Ignored = true;
        }
        return property;
    }
}

Use it like:

var bytes = new byte[] { 1, 2, 3 };
var eo = new EventObject { OtherValue = 2, MyStream = new MemoryStream(bytes) };
var s = JsonConvert.SerializeObject(eo,
  new JsonSerializerSettings { ContractResolver = new IgnoreStreamsResolver() });
// {"OtherValue":2}

By modifying other properties of the JsonProperty, you can make other changes. The one that looks like it might be most useful to you is Converter, which would let you specify your own class to define how to serialize the Stream (e.g. convert it to a byte[] and serialize that as base64).

All of this is done without any changes to the interface or implementing class.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top