Extracting information from JSON Here is a simplified version of my JSON.

{
    "Relations": [
        {
            "Type": "A",
            "Categories": [
                { "Name": "Identity" }
            ]
        },
        {
            "Type": "B",
            "Categories": [
                { "Name": "Identity" },
                {
                    "Name": "Contact Information",
                    "Type": "Phone"
                },
                { "Name": "Addresses" },
                { "Name": "Bank Accounts" }
            ]
        },
        {
            "Type": "C",
            "Categories": [
                { "Name": "Identity" },
                { "Name": "Contact Information" },
                { "Name": "Service Fields" }
            ]
        }
    ]
}


My code generates an IEnumerable (List, but I am open to suggestions if there is a more compatible option) that holds all distinct categories, meaning, when joining its values (using string.Join("\n", collection)) it contains the following JSON:

{ "Name": "Identity" }
{
    "Name": "Contact Information"
    "Type": "Phone"
}
{ "Name": "Addresses" }
{ "Name": "Bank Accounts" }
{ "Name": "Contact Information" }
{ "Name": "ServiceFields" }


This is the code:

List&lt;dynamic&gt; Method()
{
    string jString = File.ReadAllText(@"file.json");
    dynamic jObject = JsonConvert.DeserializeObject&lt;dynamic&gt;(jString);

    // The variable in questions
    var categories = new List&lt;dynamic&gt;();
    foreach (dynamic relation in jObject.Relations)
    {
        foreach (dynamic category in relation.Categories)
        {
            if (!CollectionContainsItem(categories, category))
            {
                categories.Add(category);
            }
        }
    }

    return categories;

    bool CollectionContainsItem(IEnumerable&lt;dynamic&gt; collection, JToken searchedItem)
    {
        foreach (var item in collection)
        {
            if (JToken.DeepEquals(item, searchedItem))
            {
                return true;
            }
        }
        return false;
    }
}


How to improve my code? It seems very cumbersome to me, especially the local method.

Note: I need a dynamic approach. I do not want to create C# classes for the JSON data.

Thanks!
Yes, your code can indeed be simplified, as Xiaoy312 already demonstrated:

// Obtain the Relations array:
return JObject.Parse(jsonString)["Relations"]
     // Take the categories of all relations, flattening them into a single enumerable:
    .SelectMany(relation =&gt; relation["Categories"])
    // Filter out duplicate category objects (JToken.EqualityComparer uses DeepEquals internally):
    .Distinct(JToken.EqualityComparer)
    // Materialize the results into a list:
    .ToList();


This is also more efficient:


Using dynamic means that several things (such as method overload resolution) cannot be done at compile-time but must be done at run-time, which involves additional work.
Distinct uses a set internally, so it doesn't need to compare a new category against all other categories found so far - an internal hashcode lookup is often sufficient.


dynamic can be useful, but it doesn't work with extension methods (which Linq heavily depends on), so in this case it's more of a hindrance. About the only benefit here is that relation.Categories is slightly easier to write than relation["Categories"], but you do pay for that at run-time, and it handicaps your tools (no compile-time checks, no automated refactoring). Also keep in mind that dynamic is 'contagious': any expression involving something dynamic also becomes dynamic.

Another problem is that dynamic code is less self-descriptive. Is category.Name a string, or could it be a { "name": "Identity", "id": "5" } object? That sort of uncertainty makes code more difficult to maintain, at least in my experience. Static typing can be more restrictive and cumbersome, but it gives you more guarantees and tells you more about what sort of data your program expects to handle. Unless you have a good reason to stick with dynamic (in that case, throw a .Cast&lt;dynamic&gt;() in just before the .ToList() call) I would recommend creating a Category class.

Finally, I would make the filename a parameter and rename Method to something more descriptive such as LoadCategoriesFromJsonFile, and I would put some thoughts into error handling (what if the file doesn't exist, or if it's corrupted).