问题 JSON.NET对具有Stream类型成员的对象进行序列化?


希望这是一个我忽略的简单修复。我有一个对象传递到一个事件处理程序,我想使用JSON.NET序列化该对象,如下所示:

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

似乎foo的一个或多个成员是流。我已经认识到Streams不可序列化,因为它们是数据的抽象而不是数据本身。这是有道理的。

我不知道如何序列化这个对象:

  • a)将流转换为数据并将其序列化
  • b)忽略流并序列化其余成员

对此的一个重要警告是我无法访问IEventObject或其实现,因此我无法使用属性标记标记任何这些对象。

我提出的唯一解决方案是将此对象包装在我自己的类中,对其进行适当标记,然后对其进行序列化。稍后我会反序列化回我自己的类,并将其转换为原始对象。我不喜欢这种方法,因为它涉及额外的对象和转换步骤,并且如果可能的话希望避免它。


11455
2018-04-29 14:12


起源

我遇到了同样的问题,别无选择,只能把它包装在我的一个完全可序列化的对象中。如果还有其他选择我会很高兴听到它:-) - Laurent S.
@Bartdude你可以查看我的答案。 - Tim S.
@TimS。不幸的是,在我的情况下,我最终不得不实现包装器对象,因为我没有本地访问具体类型来反序列化。否则,接受的答案是解决此问题的绝佳方案。 - jmsb


答案:


默认情况下,Json.NET将尝试序列化流的属性,这不是很有用。您可以通过创建自己的行为来修改行为 合同解析员。这是一个忽略所有的例子 Stream完全是:

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;
    }
}

使用它像:

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}

通过修改其他属性 JsonProperty,你可以做其他改变。看起来它可能对你最有用的是 Converter,这将允许您指定自己的类来定义如何序列化 Stream (例如将其转换为 byte[] 并将其序列化为base64)。

所有这些都是在不对接口或实现类进行任何更改的情况下完成的。


14
2018-04-29 14:26



这正是我想要的。我自己实施和测试后会回来查看。谢谢。 - jmsb