Json.NET是否可以对流进行序列化/反序列化?

Json.NET是否可以对流进行序列化/反序列化?,.net,serialization,json.net,.net,Serialization,Json.net,我听说Json.NET比DataContractJsonSerializer快,我想试试 但是我在JsonConvert上找不到任何采用流而不是字符串的方法 例如,对于在WinPhone上反序列化包含JSON的文件,我使用以下代码将文件内容读入字符串,然后反序列化为JSON。在我的(非常特别的)测试中,它似乎比直接从流中使用DataContractJsonSerializer反序列化慢4倍左右 // DCJS DataContractJsonSerializer dc = new DataCon

我听说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<Constants>(json);
//DCJS
DataContractJsonSerializer dc=新的DataContractJsonSerializer(类型(常量));
常量=(常量)dc.ReadObject(流);
//JSON.NET
字符串json=newstreamreader(stream.ReadToEnd();
常量=JsonConvert.DeserializeObject(json);

我做错了吗?

更新:这在当前版本中不再有效,请参阅以获取正确答案(无需否决,在旧版本中这是正确的

JsonTextReader
类与
StreamReader
一起使用,或使用直接接受
StreamReader
JsonSerializer
重载:

var serializer = new JsonSerializer();
serializer.Deserialize(streamReader);

当前版本的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源(字符串、流、文件)反序列化

公共静态类JsonHelpers
{
公共静态T CreateFromJsonStream(此流)
{
JsonSerializer serializer=新的JsonSerializer();
T数据;
使用(StreamReader StreamReader=新StreamReader(stream))
{
数据=(T)序列化程序。反序列化(streamReader,typeof(T));
}
返回数据;
}
公共静态T CreateFromJsonString(此字符串为json)
{
T数据;
使用(MemoryStream stream=newmemoryStream(System.Text.Encoding.Default.GetBytes(json)))
{
数据=CreateFromJsonStream(流);
}
返回数据;
}
公共静态T CreateFromJsonFile(此字符串文件名)
{
T数据;
使用(FileStream FileStream=newfilestream(fileName,FileMode.Open))
{
data=CreateFromJsonStream(fileStream);
}
返回数据;
}
}
反序列化现在与编写一样简单:

MyType obj1 = aStream.CreateFromJsonStream<MyType>();
MyType obj2 = "{\"key\":\"value\"}".CreateFromJsonString<MyType>();
MyType obj3 = "data.json".CreateFromJsonFile<MyType>();
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<DataItem>(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);
            }
        }
    }
}
使用系统;
使用系统诊断;
使用System.IO;
使用System.IO.Pipes;
使用系统线程;
使用System.Threading.Tasks;
使用Newtonsoft.Json;
命名空间TestJsonStream{
班级计划{
静态void Main(字符串[]参数){
使用(var writeStream=new-AnonymousPipeServerStream(PipeDirection.Out,HandleInheritability.None)){
string pipeHandle=writeStream.GetClientHandleString();
var writeTask=Task.Run(()=>{
使用(var sw=新StreamWriter(writeStream))
使用(var writer=newjsontextwriter(sw)){
var ser=新的JsonSerializer();
writer.writestarray();
对于(int i=0;i<25;i++){
serial(writer,newdataitem{Item=i});
writer.Flush();
睡眠(500);
}
writen.WriteEnd();
writer.Flush();
}
});
var readTask=Task.Run(()=>{
var sw=新秒表();
sw.Start();
使用(var readStream=新的匿名PipeClientStream(pipeHandle))
使用(var sr=新的StreamReader(readStream))
使用(var reader=newjsontextreader(sr)){
var ser=新的JsonSerializer();
如果(!reader.Read()| | reader.TokenType!=JsonToken.StartArray){
抛出新异常(“预期的数组开始”);
}
while(reader.Read()){
如果(reader.TokenType==JsonToken.EndArray)中断;
var item=ser.Deserialize(读取器);
WriteLine(“[{0}]接收到的项:{1}”,sw.appeased,item);
}
}
});
Task.WaitAll(writeTask,readTask);
writeStream.DisposeLocalCopyOfClientHandle();
}
}
类数据项{
公共int项{get;set;}
公共重写字符串ToString(){
返回string.Format(“{Item={0}}}”,Item);
}
}
}
}
请注意,当处理
匿名PipeServerStream
时,您可能会收到一个异常,我忽略了它,因为它与当前的问题无关。

公共静态void Serialize(对象值,流s)
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<T>(Stream s)
{
    using (StreamReader reader = new StreamReader(s))
    using (JsonTextReader jsonReader = new JsonTextReader(reader))
    {
        JsonSerializer ser = new JsonSerializer();
        return ser.Deserialize<T>(jsonReader);
    }
}
{ 使用(StreamWriter=新的StreamWriter)) 使用(JsonTextWriter jsonWriter=newjsontextwriter(writer)) { JsonSerializer ser=新的JsonSerializer();
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<T>(Stream s)
{
    using (StreamReader reader = new StreamReader(s))
    using (JsonTextReader jsonReader = new JsonTextReader(reader))
    {
        JsonSerializer ser = new JsonSerializer();
        return ser.Deserialize<T>(jsonReader);
    }
}