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



我正在使用 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 中以保护我宝贵的源流,但这是一个巨大的开销,尤其是在对反序列化进行试错时。

如果有一种方法可以只"阅读"

而不是"阅读和消费",感谢您的帮助,我找不到有关此的文档(我希望这篇文章能帮助其他人^^谷歌解决方案)。

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

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

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

如果有效,请告诉我。

最新更新