我正在使用 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))
(...)
如果有效,请告诉我。