带有 JsonTextReader 的 JsonPath:一次标记
Posted
技术标签:
【中文标题】带有 JsonTextReader 的 JsonPath:一次标记【英文标题】:JsonPath with JsonTextReader: Token at a Time 【发布时间】:2017-01-13 21:38:49 【问题描述】:使用 JsonTextReader 一次加载令牌 (.Load) 与使用 ReadFrom 加载整个 JSON 时,JsonPath 的工作方式不同。这是一个例子: JSON:Path="[*].person" Method=SelectTokens(path)
[
"person":
"personid": 123456
,
"person":
"personid": 798
]
当使用 .ReadFrom 时,它会返回正确的 2 个元素。如果我使用 .Load ,它将返回 0 个元素。但是,如果我将路径更改为“person”,.ReadFrom 会返回 0 个元素,而 .Load 会返回 2 个元素。
作为修复,我可以更改路径,以便将其删除到第一个“。”即 path = substring(path.index(".")+1); 但是,这感觉更像是一种 hack 而不是正确的修复。当然,我还需要确保 JSON 是一个数组,但在我的大多数情况下,它会是。
最后,我正在尝试学习如何在一次加载令牌时将 JSON 路径与数组一起使用。有什么建议吗?
Full Code
Full JSON
【问题讨论】:
【参考方案1】:在您链接到的代码中发生的情况是,它会读取标记,直到遇到一个对象,然后从该对象加载 JToken
,该对象会提前读取到该对象的末尾。
所以你最终得到的是根数组中每个项目的JToken
。然后,您可以为每个JToken
调用:
token.SelectTokens("person").OfType<JObject>()
因为您知道该属性包含一个对象。
这相当于对整个解析的 JSON 执行 "[*].person"
JsonPath。
希望我正确理解了您的问题。如果没有,请告诉我=)
更新:
根据您的 cmets,我了解您的需求。你可以做的是创建一个这样的方法:
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 路径选择器,如果您缓慢枚举,您将保持流打开的时间更长,但您的峰值内存使用率会低得多。
我希望这会有所帮助。
【讨论】:
你肯定有。在您的情况下,您像我一样修改了路径。我希望我能够利用上游的 json 路径(更靠近读者),所以我不必修改路径。同样通过修改路径,如果他们给了我 [1].person,我将不得不自己处理 [1]。有任何想法吗?感谢您的帮助。以上是关于带有 JsonTextReader 的 JsonPath:一次标记的主要内容,如果未能解决你的问题,请参考以下文章
带有 JsonTextReader 的 JsonPath:一次标记
使用 JsonTextReader 读取 JSON 会引发错误