繁体   English   中英

在 C# 中从嵌套 JSON 查找属性值,无需递归

[英]Find value of a property from a Nested JSON without recursion in C#

我想从嵌套的 JSON 数据中找到属性的值。 我有一个使用以下方法执行此操作的递归方法,并且效果很好。 有没有办法可以将其转换为迭代方法。 代码片段如下——

    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);
                }
            }
        }
}

我想将方法 GetJTokenValue() 转换为迭代器并将匹配项更改为 IEnumerable,这样我就可以避免递归并降低复杂性。 任何帮助将不胜感激。

感谢致敬,

阿米特·阿南德

您是否尝试过使用 JsonPath? 我发现它对这些情况非常有用。

您并没有真正给出源示例,所以我只是做了一些简单的事情:

//{
//  "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>());

看到它运行: https://do.netfiddle.net/zoH7FQ

希望这对你有帮助!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM