C#: Recursively get Dictonary value with deep string expression

Solution 1:

Assuming you'll always have the Dictionary<string, object> and object[] in your data structure, this approach should work:

private static object? GetSelectedValueOrDefault(this Dictionary<string, object> data, string selector)
{
    string[] selectorSegments = selector.Split('.');

    if (selectorSegments.Length == 0)
    {
        return null;
    }

    object? currentNode = data.GetValueOrDefault(selectorSegments[0]);

    if (currentNode == null)
    {
        return null;
    }

    for (int index = 1; index < selectorSegments.Length; index++)
    {
        string segment = selectorSegments[index];

        if (currentNode is not Dictionary<string, object> dictionary)
        {
            return null;
        }

        var selectorWithIndex = GetSelectorAndElementIndexOrDefault(segment);

        if (selectorWithIndex is not null &&
            currentNode is Dictionary<string, object> dict)
        {
            currentNode = dict.GetValueOrDefault(selectorWithIndex.Value.ItemSelector);
            currentNode = GetElementOrDefault(currentNode, selectorWithIndex.Value.Index);
            continue;
        }

        currentNode = dictionary.GetValueOrDefault(segment);

        if (index == selectorSegments.Length - 1)
        {
            return currentNode;
        }
    }

    return null;
}

private static object? GetElementOrDefault(object? currentNode, int index)
{
    if (currentNode is not object[] array)
    {
        return null;
    }

    if (index >= array.Length)
    {
        return null;
    }

    return array[index];
}

private static (string ItemSelector, int Index)? GetSelectorAndElementIndexOrDefault(string segment)
{
    if (!segment.Contains('['))
    {
        return null;
    }

    string[] result = segment.Split('[', ']');
    return (result[0], int.Parse(result[1]));
}

Example

var data = new Dictionary<string, object>()
{
    {
        "BookStore",
        new Dictionary<string, object>()
        {
            {
                "Name",
                "The Book Store"
            },
            {
                "Books",
                new object[]
                {
                    new Dictionary<string, object>(),
                    new Dictionary<string, object>(),
                    new Dictionary<string, object>(),
                    new Dictionary<string, object>()
                    {
                        {
                            "Author",
                            new Dictionary<string, object>()
                            {
                                {
                                    "Name",
                                    "Luke T O'Brien"
                                },
                                {
                                    "ContactDetails",
                                    new Dictionary<string, object>()
                                    {
                                        {
                                            "Address",
                                            "Some address"
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
};

Console.WriteLine(data.GetSelectedValueOrDefault("BookStore.Name"));
Console.WriteLine(data.GetSelectedValueOrDefault("BookStore.Books[3].Author.Name"));
Console.WriteLine(data.GetSelectedValueOrDefault("BookStore.Books[3].Author.ContactDetails.Address"));

Output

The Book Store
Luke T O'Brien
Some address