Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSON.NET Serialization on an object with a member of type Stream?

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.

like image 671
jmsb Avatar asked Apr 29 '14 14:04

jmsb


People also ask

What does JsonSerializer serialize do?

JsonSerializer Class (System.Text.Json)Provides functionality to serialize objects or value types to JSON and to deserialize JSON into objects or value types.

What is Jsonconvert SerializeObject C#?

SerializeObject Method (Object, Type, JsonSerializerSettings) Serializes the specified object to a JSON string using a type, formatting and JsonSerializerSettings. Namespace: Newtonsoft.Json.

What is the difference between JSON and serialization?

JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object). If you serialize this result it will generate a text with the structure and the record returned.


1 Answers

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.

like image 101
Tim S. Avatar answered Oct 16 '22 06:10

Tim S.