在Newtonsoft.Json.Linq.JObject上运行表达式谓词

本文关键字:运行 表达式 谓词 JObject Newtonsoft Json Linq | 更新日期: 2023-09-27 18:02:59

我正在创建如下所示的JObject列表。我想使用查询表达式搜索集合。在下面的示例代码中,我使用Jsonpath查询来查找类型为Buy的所有位置对象(enum Buy的int值为1)

List<JObject> list = new List<JObject>();
list.Add(JObject.FromObject(new Position() { PositionType = PositionType.Buy, Investment = new Investment() { InvestmentCode = "AAPL" } }));
list.Add(JObject.FromObject(new Position() { PositionType = PositionType.Sell, Investment = new Investment() { InvestmentCode = "AAPL" } }));
var x = list.Find(j =>
{
    JToken token =  j.SelectToken("$[?(@.PositionType == 1)]");
    return token != null;
});

SelectToken方法在谓词内返回null。我不确定我是否使用了正确的方法。是否有一种方法可以在对象上计算谓词?

在Newtonsoft.Json.Linq.JObject上运行表达式谓词

SelectTokens()文档或JSONPath标准没有很好地解释这一点,但是[?(script)]操作符可以说被定义为用于子对象的条件选择。这是因为[?()]操作符实际上是嵌套在子操作符/下标操作符中的脚本操作符的组合。来自标准:

这里是JSONPath语法元素与XPath对应元素的完整概述和并排比较。

XPath    JSONPath    Description 
/        . or []     child operator 
[]       []          subscript operator. XPath uses it to iterate over element collections and for predicates. In Javascript and JSON it is the native array operator. 
[]       ?()         applies a filter (script) expression. 
n/a      ()          script expression, using the underlying script engine. 

标准显示的[?()]操作符的唯一示例是匹配数组内对象的属性,并返回这些对象。

因此,如果我使用"$[?(@.PositionType == 1)]"[{"PositionType": 1}]上做SelectTokens(),那么返回一个对象,但是在{"PositionType": 1}上做(正如你试图在Find()谓词内做的那样)什么也不返回。

Json。NET对标准的解释并不完全是特殊的。下面是尝试使用各种JSONPath解析器将{"PositionType": 1}"$[?(@.PositionType == 1)]"$..[?(@.PositionType == 1)]匹配的结果:

  • http://www.jsonquerytool.com/-都不匹配。
  • http://jsonpath.com/-都不匹配。
  • http://jsonpath.herokuapp.com/
    • "Jayway": -两者都匹配。
    • "Gatling" - "$[?(@.PositionType == 1)]"匹配,$..[?(@.PositionType == 1)]错误。(更新:与Gatling版本0.6.7,两者匹配。)
    • "Nebhale" -两个错误。
    • "Goessner" -都不匹配。

你可以报告Json的问题。. NET的行为,但鉴于实现之间的不一致性,它可能无法得到解决。此时,与XPath相比,JSONPath标准可能还不够定义良好,也不够稳定,无法满足您的需求。

参见Newtonsoft JSON SelectToken从JSON文档的多个部分获取数据?.

如何根据JSONPath中的多个候选名称选择JToken ?