我正在使用Newtonsoft的Json.Net从以下json中选择节点:
{ "projects":[ { "name":"Project 1", "client":{ "code":"ABC", "name":"Client 1" } }, { "name":"Project 2", "client":{ "code":"DEF", "name":"Client 2" } }, { "name":"Project 3", "client":{ "code":"GHI", "name":"Client 3" } } ] }
以下C#代码段
//json is a JObject representation of the json listed above var clients = json.SelectTokens("$.projects[*].client");
产量:
[ { "code":"ABC", "name":"Client 1" }, { "code":"DEF", "name":"Client 2" }, { "code":"GHI", "name":"Client 3" } ]
现在,这很酷,我想做的是按客户端代码过滤,我认为
$.projects[*].client[?(@.code == 'DEF')]
可以,但是我显然对语法不够了解。这将返回一个空列表:
var test1 = json.SelectTokens("$.projects[*].client[?(@.code == 'DEF')]").ToList();
并且单个令牌选择器返回null:
var test2 = json.SelectToken("$.projects[*].client[?(@.code == 'DEF')]");
我在https://jsonpath.curiousconcept.com/上尝试了几种不同的配置,看来我的查询语法确实坏了。
使用Flow Communications的JSONPath 0.3.4实现(在上面的链接上),我可以使用
$..[?(@.code == 'DEF')]
但是,此语法对于Json.Net似乎无效(也不适用于同一页面上的Goessner实现)。
有人看到我在做什么错吗?
Json.NET的JSONPath解析器允许过滤器(脚本)表达式[?( )]查询候选数组项的子对象内的嵌套属性。从而
[?( )]
var test = json.SelectTokens(@"$.projects[?(@.client.code == 'DEF')].client");
根据需要返回
[ { "code": "DEF", "name": "Client 2" } ]
工作。净提琴。
经过实验,似乎jsonpath.curiousconcept.com上的JSONPath实现都不支持此语法,但是它在使用https://github.com/ashphy/jsonpath- online-evaluator的jsonpath.com上可以正常工作。该JSONPath提案只是说是一个 脚本表达式,使用底层脚本引擎* 清楚地留下了一些解释的余地是否以及如何“应该”的工作。() *
()
问题中使用的过滤器显然不适用于Json.NET,因为从10.0.3版开始,它仅正式支持将过滤器应用于数组项,而不是直接应用于对象- 请参阅问题#1256:JSONPath脚本无法正确执行讨论的对象。(尽管有时可以找到狡猾的解决方法,例如在此答案中。)但是,在过滤器中使用嵌套属性似乎是可以工作的(并且确实可以工作)。