2014-04-29 61 views
10

希望这是一个简单的解决方案,我忽略了。我已经传递到了我想要序列使用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不是可序列化的,因为它们是对数据的抽象而不是数据本身。这是有道理的。

我不知道如何通过两种反正序列化此对象:

  • 一)流转换成数据和序列化
  • B)忽略流和序列化的其余成员

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

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

+1

我面对的是相同的问题,别无选择,只能将其包装在我的完全可序列化的对象中。如果还有其他选择,我会很高兴听到它:-) –

+0

@Bartdude你可以看看我的答案。 –

+0

@TimS。不幸的是,在我的情况下,我最终不得不实现包装器对象,因为我没有本地访问要反序列化的具体类型。否则,接受的答案是解决这个问题的好办法。 – jmsb

回答

13

默认情况下,Json.NET会尝试序列化流的属性,这不是很有用。您可以通过创建自己的contract resolver来修改行为。下面是忽略所有Stream一个示例S完全:

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)。

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

+0

这正是我所寻找的。我会在自己实施和测试之后再回来查看。谢谢。 – jmsb

相关问题