JsonPath与JsonTextReader:一次令牌

时间:2017-01-13 21:38:50

标签: c# json.net jsonpath jsonreader jpath

我遇到一个问题,当使用JsonTextReader一次加载令牌(.Load)与使用ReadFrom加载整个JSON时,JsonPath的工作方式不同。这是一个例子: JSON:Path =" [*]。person"方法= SelectTokens(路径)

 [
  {
    "person": {
      "personid": 123456
    }
  },
  {
    "person": {
      "personid": 798
    }
  }
]

使用.ReadFrom时,它会返回正确的2个元素。如果我使用.Load,它将返回0个元素。但是,如果我将路径更改为" person ",则.ReadFrom会返回0个元素,而.Load会返回2个元素。

作为修复,我可以更改路径,以便它可以删除第一个"。"即 path = substring(path.index("。")+ 1); 然而,这感觉更像是一个黑客而不是一个正确的修复。当然,我还需要确保JSON是一个数组,但在我的大多数情况下,它都是。

最后,我正在尝试学习如何在一次加载令牌时使用JSON Path和数组。有什么建议吗?

Full Code

Full JSON

1 个答案:

答案 0 :(得分:1)

您链接到的代码中发生的事情是,它会在遇到对象之前读取令牌,然后从该对象加载一个JToken,该对象将提前读到此对象的末尾。 所以你最终得到的是根数组中每个项JToken。然后,您可以为每个JToken电话:

token.SelectTokens("person").OfType<JObject>()

因为您知道该属性包含一个对象。

这相当于在整个解析的JSON上执行"[*].person" JsonPath。

我希望我能正确理解你的问题。如果没有,请告诉我=)

<强>更新

根据您的评论我明白您的意思。你可以做的是创建一个这样的方法:

public IEnumerable<JToken> GetTokensByPath(TextReader tr, string path)
{
    // do our best to convert the path to a RegEx
    var regex = new Regex(path.Replace("[*]", @"\[[0-9]*\]"));
    using (var reader = new JsonTextReader(tr))
    {
        while (reader.Read())
        {
            if (regex.IsMatch(reader.Path))
                yield return JToken.Load(reader);
        }
    }
}

我根据JSON路径输入匹配路径,但我们需要尝试处理所有各种JSON路径语法,目前我只支持*。 当你有一个带有深度JSON路径选择器的海量文件时,这种方法很有用,如果你慢慢枚举,你会保持流打开的时间更长,但你的峰值内存使用率要低得多。

我希望这会有所帮助。