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

时间:2015-01-29 11:08:03

标签: 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 = serializer.Deserialize(reader, expectedType);
    }
}

然而,这种方法消耗了#39;流,意味着从流中删除第一个包含的有效Json令牌。

这很烦人。并且无意义,提供流位置来模拟消费,并且“阅读”#39;通常意味着不修改'。

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

如果有办法只是阅读'而不是“阅读和消费”,感谢您的帮助,我找不到相关的文档(我希望这篇文章能帮助其他人谷歌解决方案^^)。

2 个答案:

答案 0 :(得分:1)

JsonTextReader仅向前阅读器,这意味着无法将其重新设置回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; }
}

输出:

Name: foo
Size: 10

Name: foo
Size: 10

小提琴:https://dotnetfiddle.net/fftZV7

答案 1 :(得分:0)

读取后可以使用流。解决方案可能是将其复制到内存或文件流,如下所示:

MemoryStream ms = new MemoryStream();
inputStream.CopyTo(ms);
ms.Position = 0;
using (var textReader = new StreamReader(ms))
(...)

如果有效,请告诉我。