Reputation: 999
{
"hasLoadMore": true,
"groups": [
{
"order": 0,
"title": "string",
"total": 0,
"dateFormat": "string",
"messages": [
{
"commsId": 0,
"commsDirectionCode": "string",
"commsReasonCRSNN": 0,
"commsDeliveryChannelCDCHN": "string",
"commsDeliveryStateCode": "string",
"commsDeliveryDttm": "2017-02-14T02:20:52.836Z",
"commsSuccessFlag": true,
"commsCode": "string",
"commsName": "string",
"commsRankingNumb": 0,
"customerGrainCUSGN": 0,
"productItemCode": "string",
"sourceApplBAPPN": 0,
"sourceCommsRefn": "string",
"parentCommsId": 0,
"campaignDttm": "2017-02-14T02:20:52.836Z",
"campaignCode": "string",
"campaignName": "string",
"contentValidStartDttm": "2017-02-14T02:20:52.836Z",
"contentValidEndDttm": "2017-02-14T02:20:52.836Z",
"trackingCode": "string",
"headlineDisplayText": "string",
"contentDisplayText": "string",
"topic": "string",
"topicIconClass": "string",
"contentTemplateId": 0,
"contentTemplateVersNumb": 0,
"archiveDate": "2017-02-14T02:20:52.836Z",
"commsParameters": [
{
"commsId": 0,
"paramSeqNumb": 0,
"paramText": "string",
"paramValue": "string"
}
],
"contentTemplateParameters": [
{
"commsId": 0,
"paramSeqNumb": 0,
"paramText": "string",
"paramValue": "string"
}
],
"callToAction": [
{
"displayText": "string",
"uri": "string"
}
],
"isFlagged": true,
"isSeen": true,
"isRead": true,
"isActioned": true
}
]
}
]
}
my json is above , now i have multiple 'callToActions'
array in the above json and want to collect all of them and compare with a table.
what i am doing is below:
{
string content = Context.Response.Content.ReadAsStringAsync().Result;
var resultObjects = AllChildren(JObject.Parse(content))
.First(c => c.Type == JTokenType.Array && c.Path.Contains(decendant))
.Children<JObject>();
JArray responseList = new JArray();
foreach (JObject result in resultObjects)
{
responseList.Add(result);
}
CompareObjectToTable(responseList, table);
}
private static IEnumerable<JToken> AllChildren(JToken decendant)
{
foreach (var c in decendant.Children())
{
yield return c;
foreach (var cc in AllChildren(c))
{
yield return cc;
}
}
}
But it will only give me the "First"
array encountered but i want to gather all the array(multiple) with same descendant.Here descendant i want is callToActions
Upvotes: 1
Views: 4096
Reputation: 117046
Rather than hand-coding your own method to recursively descend the JToken
hierarchy, you can use the built-in methods JContainer.DescendantsAndSelf()
or JToken.SelectTokens()
to do it for you.
Using the first approach, you would do:
var root = (JContainer)JToken.Parse(content);
var descendant = "callToAction";
var query = root
// Recursively descend the JSON hierarchy
.DescendantsAndSelf()
// Select all properties named descendant
.OfType<JProperty>()
.Where(p => p.Name == descendant)
// Select their value
.Select(p => p.Value)
// And filter for those that are arrays.
.OfType<JArray>();
And using the second approach:
var root = JToken.Parse(content);
var descendant = "callToAction";
var query = root
// Recursively descend the JSON hierarchy using the JSONpath recursive descent operator "..", and select the values of all properties named descendant
.SelectTokens(string.Format("..{0}", descendant))
// And filter for those that are arrays.
.OfType<JArray>();
Note that I am using the JSONPath recursive descent operator ".."
to descend the hierarchy. Json.NET's SelectTokens()
method supports JSONPath query syntax which is somewhat similar to XPath.
Now, it's not clear from your question whether responseList
should be an array of arrays of results, or a flat array of results. To create an array of arrays, just do:
var responseList = new JArray(query);
To create a flattened array, do:
var responseList = new JArray(query.SelectMany(a => a));
Sample fiddle.
Upvotes: 3