当使用JsonReader时,是否有一种方法可以倒带或后退?



我试图从JSON对象输入流中读取第一个属性名称,然后根据其值,可能"倒带"并读取整个对象。

我可以很容易地读取第一个属性名,比如

JsonReader reader = ...;
while (reader.Read()) {
  if (reader.TokenType == JsonToken.PropertyName) {
    // this is the first property
    break;
  }
}

但是我看不到任何后退或倒带阅读器的方法。

虽然我知道底层流可能不支持低级搜索,但我希望我们已经读取的JSON令牌可以以某种方式倒带和重新解析。

如果这是不可能的,或者是否有任何方法只读取对象的属性名称而不解析每个属性的内容?我希望避免为了检查一个属性而阅读整个内容两次。

我对System.Text.Json也有同样的问题,我找到了一个解决方案,我想我应该在这里分享答案。

正如Levi Broderick在这里所建议的,新的Utf8JsonReader是一个结构体,这意味着它可以随意复制。

Utf8JsonReader reader2 = reader;
reader2.Read();// ... Do stuff with the copy of the reader
// Here the initial reader didn't change and is still where you left it.

这样,你可以像我在这里或那里那样解析两次数据

与Newtonsoft

。Json,我最终使用JToken.ReadFrom(reader),然后从那里做我的事情。请看下面的代码

JToken token = JToken.ReadFrom(reader);
var left = token.ToObject<TLeft>(serializer);
var right = token.ToObject<TRight>(serializer);

No。JsonReader为正向只读器。如果不从头完全重新解析,就没有办法"倒带"或返回到较早的阶段。如果你希望能够看到早期的信息,那么你需要在读取它时将其存储到变量中。

JsonReader确实提供了一个Skip方法,该方法可用于跳过特定令牌的子元素。因此,如果您读取了您不感兴趣的属性名称,并且下一个令牌是对象或数组的开始,则可以使用Skip直接移动到该对象或数组的结束令牌。

下面是一个简单的例子,它使用这种技术只读取JSON对象的根属性名,但跳过所有值。

string json = @"
{
  ""resultCode"": 200,
  ""message"": ""OK"",
  ""searchTerms"": [
    {
      ""attribute"": ""keywords"",
      ""operator"": ""contains"",
      ""values"": [ ""ipsum"" ]
    }
  ],
  ""count"": 2,
  ""items"": [
    {
      ""id"": 1,
      ""name"": ""foo"",
      ""sizes"": [ ""small"", ""meduim"", ""large"" ],
      ""description"": ""Lorem ipsum dolor sit amet""
    },
    {
      ""id"": 2,
      ""name"": ""bar"",
      ""sizes"": [ ""tiny"", ""huge"" ],
      ""description"": ""Neque porro quisquam est qui dolorem ipsum""
    }
  ]
}";
using (StringReader sr = new StringReader(json))
using (JsonTextReader reader = new JsonTextReader(sr))
{
    while (reader.Read())
    {
        if (reader.TokenType == JsonToken.PropertyName)
        {
            string propName = (string)reader.Value;
            Console.WriteLine(propName);
            // advance to property value
            reader.Read();
            // if the value is an object or array, skip over its children
            if (reader.TokenType == JsonToken.StartObject ||
                reader.TokenType == JsonToken.StartArray)
                reader.Skip();
        }
    }
}
输出:

resultCode
message
searchTerms
count
items

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

相关内容

  • 没有找到相关文章

最新更新