0

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

1
  • What have you tried to accomplish that? You could start with changing the return type to IEnumerable<JToken> remove the matches parameter and use yield return. Commented Apr 24, 2020 at 11:11

1 Answer 1

1

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!

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.