Json.NET JSONPath query not returning expected results

一曲冷凌霜 提交于 2019-12-17 20:14:33

问题


I'm using Newtonsoft's Json.Net to select nodes from the following 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"
         }
      }
   ]
}

The following c# snippet

//json is a JObject representation of the json listed above
var clients =  json.SelectTokens("$.projects[*].client");

Yields:

[  
   {  
      "code":"ABC",
      "name":"Client 1"
   },
   {  
      "code":"DEF",
      "name":"Client 2"
   },
   {  
      "code":"GHI",
      "name":"Client 3"
   }
]

Which is cool, now, what I'd like to do is filter by client code, I would think that

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

would work, but I obviously don't understand the syntax well enough. This returns an empty list:

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

And the single token selector returns a null:

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

I tried a few different configurations on https://jsonpath.curiousconcept.com/ and it seems my query syntax is indeed broken.

Using Flow Communications' JSONPath 0.3.4 implementation (on the above link) I can get the client using

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

however, this syntax does not seem valid for Json.Net (nor the Goessner implementation on the same page).

Anyone see what I'm doing wrong?


回答1:


Json.NET's JSONPath parser allows the filter (script) expression [?( )] to query for nested properties inside child objects of the candidate array item(s). Thus

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

returns, as desired,

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

Working .Net fiddle.

Upon experimentation it seems none of the JSONPath implementations at jsonpath.curiousconcept.com support this syntax, however it works correctly at jsonpath.com which uses https://github.com/ashphy/jsonpath-online-evaluator. The JSONPath proposal simply states that () is a script expression, using the underlying script engine which clearly leaves some room for interpretation as to whether and how this "should" work.

The filters used in the question apparently do not work with Json.NET because, as of version 10.0.3, it only officially supports applying filters to array items and not directly to objects -- see Issue #1256: JSONPath scripts not executing correctly for objects for a discussion. (Though sometimes cunning workarounds can be found, for instance in this answer.) Using nested properties inside filters, however, seems to be intended to work (and does work).



来源:https://stackoverflow.com/questions/45297883/json-net-jsonpath-query-not-returning-expected-results

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!