带有 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 会引发错误

StreamReader 和 JsonTextReader 的反序列化不起作用

带有jquery的jsonp [关闭]

带有 jsonp 的 AngularJS 资源服务失败

带有 HttpHeaders 的 Angular 5 JSONP 请求