Reputation: 1109
I want to find the value of a property from a nested JSON data. I have a a recursive approach of doing this using the following methods and it works well. Is there a way I can convert this to an Iterative method. The code snippet is as follows --
public static class JsonExtensions
{
/// <summary>
/// Finds the value of a JToken from the given JSON data for the given property name.
/// If the resultant JToken have multiple occurrence at different levels of JSON data the this methods returns the first or default.
/// </summary>
/// <param name="containerToken">Given JSON data.</param>
/// <param name="propertyName">Property name whose value needs to be find.</param>
/// <returns></returns>
public static string FindJToken(this JToken containerToken, string propertyName)
{
if (containerToken == null)
{
throw new ArgumentNullException(nameof(containerToken));
}
if (string.IsNullOrWhiteSpace(propertyName))
{
throw new ArgumentException("Parameter Cannot be Null, Empty or White spaces.", nameof(propertyName));
}
List<JToken> matches = new List<JToken>();
GetJTokenValue(containerToken, propertyName, matches);
return matches.FirstOrDefault()?.ToString();
}
/// <summary>
/// Recursive method to find value of the given JToken / property name from the given JSON
/// </summary>
/// <param name="containerToken">Given JSON data</param>
/// <param name="propertyName">Property name whose value needs to be find.</param>
/// <param name="matches">List of matching tokens</param>
private static void GetJTokenValue(JToken containerToken, string propertyName, List<JToken> matches)
{
if (containerToken.Type == JTokenType.Object)
{
foreach (JProperty child in containerToken.Children<JProperty>())
{
if (child.Name == propertyName)
{
matches.Add(child.Value);
}
GetJTokenValue(child.Value, propertyName, matches);
}
}
else if (containerToken.Type == JTokenType.Array)
{
foreach (JToken child in containerToken.Children())
{
GetJTokenValue(child, propertyName, matches);
}
}
}
}
I want to convert the method GetJTokenValue() as an iterator and change the matches into IEnumerable so that I can avoid recursion and reduce the complexity . Any help will be appreciated.
Thanks and Regards,
Amit Anand
Upvotes: 0
Views: 712
Reputation: 718
Have you tried using JsonPath? I find it very useful for these sorts of situations.
You didn't really give a source example so I just made up something simple:
//{
// "ToBeFound": "test",
// "lala": [
// {
// "ToBeFound": "test"
// },
// {
// "NotToBeFound": "test2"
// }
// ]
//}
var source = JToken.Parse(@"{ ""ToBeFound"": ""test"", ""lala"": [ { ""ToBeFound"": ""test"" }, { ""NotToBeFound"": ""test2"" } ] }");
var results = source.SelectTokens("$..ToBeFound");
foreach(JToken result in results)
Console.WriteLine(result.Value<string>());
See it run: https://dotnetfiddle.net/zoH7FQ
Hope this helps you!
Upvotes: 1