Home > Software design >  c# Json retrieve a specific node with his level
c# Json retrieve a specific node with his level

Time:07-15

I've created two c# classes and then deserialize the Json returned to work with it natively.

class structureTree
{
    public structureChildren[] children { get; set; }
}

class structureChildren
{
    public structureChildren[] children { get; set; }
    public string myentity { get; set; }
    public bool sonGuide { get; set; }
    public string from { get; set; }
    public Int64 structureId { get; set; }
    public string to { get; set; }
}

The Data returned is like this

[
  {
    "children": [
      {
        "children": [
          {
            "children": [
              {
                "children": [],
                "myentity": "ENT2_A",
                "from": "2019-10-01",
                "structureId": 34353,
                "to": null
              },
              {
                "children": [
                  {
                    "children": [],
                    "myentity": "ENT3_A",
                    "from": "2019-10-01",
                    "structureId": 34349,
                    "to": null
                  },
                  {
                    "children": [],
                    "myentity": "ENT3_B",
                    "from": "2019-10-01",
                    "structureId": 34351,
                    "to": null
                  }
                ],
                "myentity": "ENT2_B",
                "from": "2019-10-01",
                "structureId": 34348,
                "to": null
              }
            ],
            "myentity": "ENT1_A",
            "from": "2019-10-01",
            "structureId": 34348,
            "to": null
          }
        ],
           "myentity": "ENT0_A",
            "from": "2019-10-01",
            "structureId": 34348,
            "to": null

      }
    ]
    }   
]   

I need to get all "myentity" elements and if it's possible in which level resides.

If not possible obtain level, another way is get all "myentity" for each level.

CodePudding user response:

Probably there are much better and elegant ways of doing this. This is without thinking on it much:

void Main()
{
    var st = JsonConvert.DeserializeObject<List<structureTree>>(myjson);
    List<Tuple<string,int>> entities = new List<System.Tuple<string, int>>();
    foreach (var stc in st)
    {
        foreach (var sc in stc.children)
        {
            GetMyEntity(entities, sc, 0);
        }
    }
    foreach (var e in entities)
    {
        Console.WriteLine($"{e.Item1}, {e.Item2}");
    }
}
void GetMyEntity(List<Tuple<string,int>> entities, structureChildren c, int level)
{
    entities.Add(Tuple.Create(c.myentity,level));
    level  ;
    foreach (var sc in c.children)
    {
        GetMyEntity(entities, sc, level);
    }
}
class structureTree
{
    public structureChildren[] children { get; set; }


}
class structureChildren
{
    public structureChildren[] children { get; set; }
    public string myentity { get; set; }
    public bool sonGuide { get; set; }
    public string from { get; set; }
    public Int64 structureId { get; set; }
    public string to { get; set; }
}

static readonly string myjson = @"[
  {
    ""children"": [
      {
        ""children"": [
          {
            ""children"": [
              {
                ""children"": [],
                ""myentity"": ""ENT3_A"",
                ""from"": ""2019-10-01"",
                ""structureId"": 34353,
                ""to"": null
              },
              {
                ""children"": [
                  {
                    ""children"": [],
                    ""myentity"": ""ENT3_B"",
                    ""from"": ""2019-10-01"",
                    ""structureId"": 34349,
                    ""to"": null
                  },
                  {
                    ""children"": [],
                    ""myentity"": ""ENT3_C"",
                    ""from"": ""2019-10-01"",
                    ""structureId"": 34351,
                    ""to"": null
                  }
                ],
                ""myentity"": ""ENT2_A"",
                ""from"": ""2019-10-01"",
                ""structureId"": 34348,
                ""to"": null
              }
            ],
            ""myentity"": ""ENT1_1"",
            ""from"": ""2019-10-01"",
            ""structureId"": 34348,
            ""to"": null
          }
        ]
      }
    ]
  }
]";

Output:

, 0
ENT1_1, 1
ENT3_A, 2
ENT2_A, 2
ENT3_B, 3
ENT3_C, 3

CodePudding user response:

You can do it in two ways, with a stack/queue or recursion. I personally prefer stacks since recursion is hard(er) to debug. This is a quick draft. I'm sure someone else can give you a fancy recursion version with Linq, but I think this illustrates the steps you need to take better.

using System;
using System.Collections.Generic;

public class Program
{       
    public static void Main()
    {       
        var structure = new StructureTree();
        var currentStack = new Stack<StructureChildren>(structure.children);
        var nextStack = new Stack<StructureChildren>();
        var flatStructure = new List<KeyValuePair<int, string>>();
        int currentLevel = 0;
        bool loop = true;
        
        while (loop)
        {
            var currentItem = currentStack.Pop();
            
            foreach (var child in currentItem.children)
                nextStack.Push(child);
            
            flatStructure.Add(new KeyValuePair<int, string>(currentLevel, currentItem.myentity));
            
            if (currentStack.Count == 0)
            {
                if (nextStack.Count == 0)
                    break;

                currentLevel  ;
                currentStack = new Stack<StructureChildren>(nextStack);
                nextStack.Clear();
            }
        }       
    }
    
    public class StructureTree
    {
        public StructureChildren[] children { get; set; }
    }
    
    public class StructureChildren
    {
        public StructureChildren[] children { get; set; }
        public string myentity { get; set; }
        public bool sonGuide { get; set; }
        public string from { get; set; }
        public Int64 structureId { get; set; }
        public string to { get; set; }
    }
}

PS: Please look into the naming convention provided by Microsoft. Class names should be CapitalizedAtEveryWord and property names too. Your current naming scheme is typically used for Java, not C#.

  • Related