2017-07-25 185 views
4

我使用Newtonsoft的Json.Net选择从以下JSON节点:Json.NET JSONPath查询没有返回预期的结果

{ 
    "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(); 

和单个令牌选择返回一个空:

var test2 = json.SelectToken("$.projects[*].client[?(@.code == 'DEF')]"); 

我试过https://jsonpath.curiousconcept.com/几种不同的配置,它似乎我的查询语法确实打破。

使用流动通讯JSONPath 0.3.4执行(以上链接),我可以使用

$..[?(@.code == 'DEF')] 

但得到的客户端,这句法似乎并不适用于Json.Net(也没有对Goessner实施相同的页面)。

有人看到我在做什么错了吗?

+0

你可以尝试交换jayway的实现,这将工作。 https://github.com/json-path/JsonPath –

回答

3

Json.NET的JSONPath parser允许筛选器(脚本)表达式[?()]查询候选数组项目的子对象内的嵌套属性。因此

var test = json.SelectTokens(@"$.projects[?(@.client.code == 'DEF')].client"); 

回报,如需要的话,

[ 
    { 
    "code": "DEF", 
    "name": "Client 2" 
    } 
] 

工作.Net fiddle

经过实验,似乎在jsonpath.curiousconcept.com支持此语法的JSONPath实现似乎没有,但它在jsonpath.com正常工作,它使用https://github.com/ashphy/jsonpath-online-evaluatorJSONPath proposal简单地指出,()是一个脚本表达式,使用底层脚本引擎,这清楚地留下了解释这个“应该”是否以及如何工作的空间。因为,由于10.0.3版本中question使用显然不符合Json.NET工作

滤波器,它只正式支持应用滤镜数组的项目,而不是直接对象 - 看到Issue #1256: JSONPath scripts not executing correctly for objects的讨论。 (尽管有时可以找到狡猾的解决方法,例如在this answer中。)但是,在过滤器内部使用嵌套属性似乎是有用的(并且确实有效)。

+0

看来,在线实现的行为有所不同。它在我的解决方案中完美工作,**谢谢**。为了理解逻辑,过滤器应该应用于数组? - 在这个例子中,你过滤项目[...],因为它是一个数组,但不是在客户端{...},因为它是一个单一的对象(因此无法过滤)? – Jaco

+0

@Jaco - *该过滤器应该应用于数组?*是的。看来Json.NET从10.0.3开始并没有正式支持过滤对象内部的对象。请参阅[问题#1256:JSONPath脚本未正确执行对象](https://github.com/JamesNK/Newtonsoft.Json/issues/1256)。虽然有时可以找到狡猾的解决方法,例如在[本答案](https://stackoverflow.com/a/39453636/3744182)中。 – dbc