Newtonsoft Json.net - 如何序列化流的内容?

use*_*169 6 c# json.net

我需要转换为内存流的JSON 任意内容.这是我想要做的一个简单示例:

class Program
{
    class TestClass { public int Test1;}
    static void Main(string[] args)
    {
        var ms = new MemoryStream();
        var writer = new StreamWriter(ms);
        writer.Write(new TestClass());
        writer.Flush();
        ms.Position = 0;

        var json = JsonConvert.SerializeObject(/*???*/, Formatting.Indented);
        Console.Write(json);
        Console.Read();
    }
}
Run Code Online (Sandbox Code Playgroud)

不知道要传递给SerializeObject方法的内容.如果我传递MemoryStream(变量ms),我会收到一个错误:

Newtonsoft.Json.dll中发生未处理的"Newtonsoft.Json.JsonSerializationException"类型异常

附加信息:从'System.IO.MemoryStream'上的'ReadTimeout'获取值时出错.

是否可以序列化流的任意内容?

谢谢

Dar*_*acz 17

使用转换器可以实现对MemoryStream内容的序列化和反序列化:

public class MemoryStreamJsonConverter : JsonConverter
{
  public override bool CanConvert(Type objectType)
  {
     return typeof(MemoryStream).IsAssignableFrom(objectType);
  }

  public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  {
     var bytes = serializer.Deserialize<byte[]>(reader);
     return bytes != null ? new MemoryStream(bytes) : new MemoryStream();
  }

  public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  {
     var bytes = ((MemoryStream)value).ToArray();
     serializer.Serialize(writer, bytes);
  }
}
Run Code Online (Sandbox Code Playgroud)

然后你的代码看起来像那样(我将"new TestClass()"更改为"Test string"以便于比较json序列化和反序列化):

private void CheckJsonSerialization()
{
   var ms = new MemoryStream();
   var writer = new StreamWriter(ms);
   writer.WriteLine("Test string");
   writer.Flush();
   ms.Position = 0;

   var json = JsonConvert.SerializeObject(ms, Formatting.Indented, new MemoryStreamJsonConverter());
   var ms2 = JsonConvert.DeserializeObject<MemoryStream>(json, new MemoryStreamJsonConverter());
   var reader = new StreamReader(ms2);
   var deserializedString = reader.ReadLine();

   Console.Write(json);
   Console.Write(deserializedString);
   Console.Read();
}
Run Code Online (Sandbox Code Playgroud)

当Stream是序列化对象的属性时,也可以使用这种转换器:

  public class ClassToCheckSerialization
  {
     public string StringProperty { get; set; }

     [JsonConverter(typeof(MemoryStreamJsonConverter))]
     public Stream StreamProperty { get; set; }
  }

  private void CheckJsonSerializationOfClass()
  {
     var data = new ClassToCheckSerialization();
     var ms = new MemoryStream();
     const string entryString = "Test string inside stream";
     var sw = new StreamWriter(ms);
     sw.WriteLine(entryString);
     sw.Flush();
     ms.Position = 0;
     data.StreamProperty = ms;
     var json = JsonConvert.SerializeObject(data);

     var result = JsonConvert.DeserializeObject<ClassToCheckSerialization>(json);
     var sr = new StreamReader(result.StreamProperty);
     var stringRead = sr.ReadLine();
     //Assert.AreEqual(entryString, stringRead);
  }
Run Code Online (Sandbox Code Playgroud)