C# 防止JsonTextReader在反序列化期间使用流

C# 防止JsonTextReader在反序列化期间使用流,c#,json,json.net,C#,Json,Json.net,我正在使用Json.Net来使用一些可查找的流 // reset the input stream, in case it was previously read inputStream.Position = 0; using (var textReader = new StreamReader(inputStream)) { using (var reader = new JsonTextReader(textReader)) { deserialized =

我正在使用Json.Net来使用一些可查找的流

// reset the input stream, in case it was previously read
inputStream.Position = 0;
using (var textReader = new StreamReader(inputStream))
{
    using (var reader = new JsonTextReader(textReader))
    {
        deserialized = serializer.Deserialize(reader, expectedType);
    }
}
但是,此方法“使用”流,这意味着从流中删除第一个包含的有效Json令牌

这很烦人。毫无意义的是,提供流位置是为了模拟消耗,“读取”通常意味着“不修改”

当然,我可以将流转储到MemoryStream中以保护我宝贵的源流,但这是一个巨大的开销,尤其是在对反序列化进行尝试和出错时


如果有一种方法只是“阅读”而不是“阅读和消费”,谢谢你的帮助,我找不到关于这方面的文档(我希望这篇文章能帮助其他人用谷歌搜索解决方案。^^)。

一旦阅读,可能会消费流。解决方案可以是将其复制到内存或文件流,如下所示:

MemoryStream ms = new MemoryStream();
inputStream.CopyTo(ms);
ms.Position = 0;
using (var textReader = new StreamReader(ms))
(...)
请让我知道它是否工作。

是一个仅向前的读取器,这意味着不能将它设置回JSON中较早的位置以重新读取它的一部分,即使底层流支持查找。但是,正如您所说,读者实际上并没有“消费”流。如果将读卡器上的
CloseInput
属性设置为
false
,以防止它在释放时关闭底层读卡器和流,则可以将流放回起始位置,并在同一流上打开新的读卡器以重新读取JSON。下面是一个演示两次读取同一流的简短程序:

class Program
{
    static void Main(string[] args)
    {
        string json = @"{ ""name"": ""foo"", ""size"": ""10"" }";
        MemoryStream inputStream = new MemoryStream(Encoding.UTF8.GetBytes(json));

        JsonSerializer serializer = new JsonSerializer();

        using (var textReader = new StreamReader(inputStream))
        {
            for (int i = 0; i < 2; i++)
            {
                inputStream.Position = 0;

                using (var reader = new JsonTextReader(textReader))
                {
                    reader.CloseInput = false;

                    Widget w = serializer.Deserialize<Widget>(reader);

                    Console.WriteLine("Name: " + w.Name);
                    Console.WriteLine("Size: " + w.Size);
                    Console.WriteLine();
                }
            }
        }
    }
}

class Widget
{
    public string Name { get; set; }
    public int Size { get; set; }
}

Fiddle:

OP在问题中明确表示,由于高开销,他不想复制流。
Name: foo
Size: 10

Name: foo
Size: 10