我听说Json.NET比DataContractJsonSerializer更快,想试一试......
但我在JsonConvert上找不到任何采用流而不是字符串的方法.
例如,为了在WinPhone上反序列化包含JSON的文件,我使用以下代码将文件内容读入字符串,然后反序列化为JSON.在我的(非常临时)测试中,使用DataContractJsonSerializer直接从流中反序列化似乎要慢4倍...
// DCJS DataContractJsonSerializer dc = new DataContractJsonSerializer(typeof(Constants)); Constants constants = (Constants)dc.ReadObject(stream); // JSON.NET string json = new StreamReader(stream).ReadToEnd(); Constants constants = JsonConvert.DeserializeObject(json);
我做错了吗?
当前版本的Json.net不允许您使用接受的答案代码.目前的替代方案是:
public static object DeserializeFromStream(Stream stream) { var serializer = new JsonSerializer(); using (var sr = new StreamReader(stream)) using (var jsonTextReader = new JsonTextReader(sr)) { return serializer.Deserialize(jsonTextReader); } }
文档:从文件流中反序列化JSON
public static void Serialize(object value, Stream s) { using (StreamWriter writer = new StreamWriter(s)) using (JsonTextWriter jsonWriter = new JsonTextWriter(writer)) { JsonSerializer ser = new JsonSerializer(); ser.Serialize(jsonWriter, value); jsonWriter.Flush(); } } public static T Deserialize(Stream s) { using (StreamReader reader = new StreamReader(s)) using (JsonTextReader jsonReader = new JsonTextReader(reader)) { JsonSerializer ser = new JsonSerializer(); return ser.Deserialize (jsonReader); } }
更新:这在当前版本中不再有效,请参阅下面的正确答案(无需拒绝投票,这在旧版本中是正确的).
使用JsonTextReader
带有a 的类StreamReader
或使用直接带有的JsonSerializer
重载StreamReader
:
var serializer = new JsonSerializer(); serializer.Deserialize(streamReader);
我编写了一个扩展类来帮助我从JSON源(字符串,流,文件)反序列化.
public static class JsonHelpers { public static T CreateFromJsonStream(this Stream stream) { JsonSerializer serializer = new JsonSerializer(); T data; using (StreamReader streamReader = new StreamReader(stream)) { data = (T)serializer.Deserialize(streamReader, typeof(T)); } return data; } public static T CreateFromJsonString (this String json) { T data; using (MemoryStream stream = new MemoryStream(System.Text.Encoding.Default.GetBytes(json))) { data = CreateFromJsonStream (stream); } return data; } public static T CreateFromJsonFile (this String fileName) { T data; using (FileStream fileStream = new FileStream(fileName, FileMode.Open)) { data = CreateFromJsonStream (fileStream); } return data; } }
反序列化现在和编写一样简单:
MyType obj1 = aStream.CreateFromJsonStream(); MyType obj2 = "{\"key\":\"value\"}".CreateFromJsonString (); MyType obj3 = "data.json".CreateFromJsonFile ();
希望它会帮助别人.
我到达了这个问题,寻找一种方法将一个开放的对象列表流式传输到System.IO.Stream
另一端并从另一端读取它们,而不是在发送之前缓冲整个列表.(具体来说,我是通过Web API从MongoDB传输持久化对象.)
@Paul Tyng和@Rivers在回答原始问题方面表现出色,我用他们的答案为我的问题建立了一个概念验证.我决定在这里发布我的测试控制台应用,以防其他人面临同样的问题.
using System; using System.Diagnostics; using System.IO; using System.IO.Pipes; using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json; namespace TestJsonStream { class Program { static void Main(string[] args) { using(var writeStream = new AnonymousPipeServerStream(PipeDirection.Out, HandleInheritability.None)) { string pipeHandle = writeStream.GetClientHandleAsString(); var writeTask = Task.Run(() => { using(var sw = new StreamWriter(writeStream)) using(var writer = new JsonTextWriter(sw)) { var ser = new JsonSerializer(); writer.WriteStartArray(); for(int i = 0; i < 25; i++) { ser.Serialize(writer, new DataItem { Item = i }); writer.Flush(); Thread.Sleep(500); } writer.WriteEnd(); writer.Flush(); } }); var readTask = Task.Run(() => { var sw = new Stopwatch(); sw.Start(); using(var readStream = new AnonymousPipeClientStream(pipeHandle)) using(var sr = new StreamReader(readStream)) using(var reader = new JsonTextReader(sr)) { var ser = new JsonSerializer(); if(!reader.Read() || reader.TokenType != JsonToken.StartArray) { throw new Exception("Expected start of array"); } while(reader.Read()) { if(reader.TokenType == JsonToken.EndArray) break; var item = ser.Deserialize(reader); Console.WriteLine("[{0}] Received item: {1}", sw.Elapsed, item); } } }); Task.WaitAll(writeTask, readTask); writeStream.DisposeLocalCopyOfClientHandle(); } } class DataItem { public int Item { get; set; } public override string ToString() { return string.Format("{{ Item = {0} }}", Item); } } } }
请注意,处理时可能会收到异常AnonymousPipeServerStream
,我忽略了这一点,因为它与手头的问题无关.