简体   繁体   中英

C# Extract JSON from nested array

I'm trying to iterate through nested JSON arrays using C# and JSON.NET. The JSON represents categories for an online webstore - below is an example. My goal is to create a list of all of the names of categories.

{
  "id": 2,
  "parent_id": 1,
  "name": "Main Category List",
  "is_active": true,
  "position": 1,
  "level": 1,
  "product_count": 0,
  "children_data": [
    {
      "id": 9,
      "parent_id": 2,
      "name": "Mens Clothing",
      "is_active": true,
      "position": 6,
      "level": 2,
      "product_count": 0,
      "children_data": []
    },
    {
      "id": 8,
      "parent_id": 2,
      "name": "Womens Clothing",
      "is_active": true,
      "position": 7,
      "level": 2,
      "product_count": 0,
      "children_data": [
        {
          "id": 223,
          "parent_id": 8,
          "name": "Outdoor Clothing",
          "is_active": true,
          "position": 1,
          "level": 3,
          "product_count": 0,
          "children_data": []
        },
        {
          "id": 224,
          "parent_id": 8,
          "name": "Hiking Clothing",
          "is_active": true,
          "position": 2,
          "level": 3,
          "product_count": 0,
          "children_data": []
        },
        {
          "id": 596,
          "parent_id": 8,
          "name": "Dresses",
          "is_active": true,
          "position": 3,
          "level": 3,
          "product_count": 0,
          "children_data": [
            {
              "id": 694,
              "parent_id": 596,
              "name": "Summer Dresses",
              "is_active": true,
              "position": 13,
              "level": 4,
              "product_count": 0,
              "children_data": [
                {
                  "id": 720,
                  "parent_id": 694,
                  "name": "Accessories",
                  "is_active": true,
                  "position": 1,
                  "level": 5,
                  "product_count": 0,
                  "children_data": [ ]
                }
              ]
            }
          ]
        }
      ]
    },
    {
      "id": 10,
      "parent_id": 2,
      "name": "Sale & Clearance",
      "is_active": true,
      "position": 8,
      "level": 2,
      "product_count": 0,
      "children_data": []
    }
  ]
}

There could be varying levels of categories and I need to parse every one. I want to get every category and create a map. For example (Main Category List --> Women's Clothing --> Outdoor Clothing). I'm thinking I can check the depth of children data but I don't know how to keep checking deeper and deeper into the next Json object.

JObject responseObject = JObject.Parse(response.Content);


foreach (JObject category in getCatResponseObj.SelectToken("children_data"))
{
    while loop checking depth of children_data



}

This appears to be a recursively defined structure. You should create a function to extract the values of each of the children so you could reuse it recursively.

IEnumerable<string> GetCategoryNames(JObject data)
{
    yield return (string)data["name"];
    foreach (var name in data["children_data"].Cast<JObject>().SelectMany(GetCategoryNames))
        yield return name;
}

Then call it on the root object to get your names putting in a list or whatever.

var obj = JObject.Parse(response.Content);
var names = GetCategoryNames(obj).ToList();

Otherwise, if you want to indiscriminately get all names in the object tree, just keep in mind that SelectToken() / SelectTokens() also takes json path queries. So to get all names of all descendants, you'd just do this:

let names = obj.SelectTokens("..name").ToList();

Were it me, I would create the most complete JSON file I can come up with (including all possible entries), then use json2csharp or an equivalent tool to create c# classes then deserialize the Json and work with it natively. You may have to massage the results a bit - but I think you can get there. If that didn't work, I would use Newtonsofts JSON LINQ Features (documentation) . JToken gives you parent / children combinations that allows you to traverse up and down the tree. The samples in the documentation are really good, so no need of my filling up the page with duplicate info.

(Generated from your example)

public class ChildrenData
{
    public int id { get; set; }
    public int parent_id { get; set; }
    public string name { get; set; }
    public bool is_active { get; set; }
    public int position { get; set; }
    public int level { get; set; }
    public int product_count { get; set; }
    public List<object> children_data { get; set; }
}

public class RootObject
{
    public int id { get; set; }
    public int parent_id { get; set; }
    public string name { get; set; }
    public bool is_active { get; set; }
    public int position { get; set; }
    public int level { get; set; }
    public int product_count { get; set; }
    public List<ChildrenData> children_data { get; set; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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