JsonPath filters on multi-nav properties, but fails on single object
See original GitHub issueI’m struggling to understand what’s wrong with my queries that attempt to traverse a hierarchical JSON output of SAP SuccessFactors OData endpoint. JSON Path recursive descent and filtering seems to work inconsistently: it works on arrays (JArray), but fails on single objects (JObject).
Source/destination types
No specific types, actually, just fiddling with JSON Path JToken.SelectToken or SelectTokens methods output. The business case was to process SAP SuccessFactors REST OData endpoint query results.
Source/destination JSON
Simplified JSON may look like this.
{
"d": {
"results": [{
"__metadata": {
"type": "SFOData.PerPersonal"
},
"property": "value",
"objectNav": {
"__metadata": {
"type": "SFOData.PerPerson"
},
"personIdExternal":"1234",
"arrayNav": {
"results": [{
"__metadata": {
"type": "SFOData.PerPhone"
},
"phoneType": "21735",
"phoneNumber": "+7 (000) 000-42-34"
}, {
"__metadata": {
"type": "SFOData.PerPhone"
},
"phoneType": "10876",
"phoneNumber": "775715"
}]
}
}
}]
}
}
Expected behavior
I expect the SelectToken/SelectTokens with recursive descent operator to work consistently regardless of the presence of array or lack thereof.
Actual behavior
Successful query JSON Path "$..*[?(@.__metadata.type=='SFOData.PerPhone')].phoneNumber" yields "775715"
No results for JSON Path "$..*[?(@.__metadata.type=='SFOData.PerPerson')].personIdExternal"
Steps to reproduce
[Test]
public async Task SfODataDemo()
{
JToken sfodataJson;
string[] successfulQueries = new [] {
"$..results[?(@.__metadata.type=='SFOData.PerPhone')].phoneNumber",
"$..*[?(@.__metadata.type=='SFOData.PerPhone')].phoneType",
"$..*[?(@.__metadata.type=='SFOData.PerPhone')].phoneNumber"
}, failingQueries = new [] {
"$..*[?(@.__metadata.type=='SFOData.PerPerson')].personIdExternal",
};
// read asynchronously from a file
using (TextReader textReader = new StreamReader(new FileStream(ResolvePath(@"sfodata.json"), FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true)))
{
sfodataJson = await JToken.LoadAsync(new JsonTextReader(textReader));
}
foreach (string jsonPath in successfulQueries){
JToken record = sfodataJson.SelectToken(jsonPath);
}
foreach (string jsonPath in failingQueries){
JToken record = sfodataJson.SelectToken(jsonPath);
}
}
Issue Analytics
- State:
- Created 3 years ago
- Comments:6 (1 by maintainers)
Top Results From Across the Web
How to filter a non-array in JsonPath
I was trying to test if a given property was equal to a given string, and if so, return the entire root object....
Read more >[Fixed] Workflows JSONpath Issue: Array brackets always ...
[Fixed] Workflows JSONpath Issue: Array brackets always present when using filters. This issue is now fixed. The root cause was a shim we...
Read more >JSONPath Reference | ReadyAPI Documentation
All of the JSONPath expressions (including property names and values) are case-sensitive. Filters. Apply filters to JSON arrays and objects to get a...
Read more >Using JSONPath effectively in AWS Step Functions
This post uses a sample application to highlight effective use of JSONPath and data filtering strategies that can be used in Step Functions....
Read more >Writing JSONPath Expressions - Hevo Data
JSONPath is a query language for JSON, similar to XPath for XML. It allows you to select and extract data from a JSON...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
_metadata has one underscore.
So I took the sources and by debugging, found that
*
is to blame in some cases.Having processed the same JSON with JsonPath expressions differing only in the asterisk before the brackets, the one without asterisk works as expected, while the one with an asterisk returns an empty set.