Click here to Skip to main content
14,926,216 members
Articles / Programming Languages / JScript .NET
Technical Blog
Posted 30 May 2016

Stats

23.9K views
9 bookmarked

Dynamically Building JSON Tree For Use In JavaScript Components Using C#

Rate me:
Please Sign up or sign in to vote.
5.00/5 (5 votes)
31 May 2016CPOL3 min read
Dynamically building JSON tree for use In JavaScript components using C#

Dynamically Building JSON Tree For Use In Javascript Components Using C#

Introduction

These days, many JavaScript components use JSON when it comes to working with data, the reason is obvious enough, but some components that build some kind of tree structure like this one, are going to need a JSON tree. Building a static JSON tree is easy, but how do you build a dynamic JSON tree and pass them to the components like the one mentioned? That's what this post is all about.

First Step: Building the Representation of a Tree as a Type

The first step we need to take, is to build a tree in C#, and then convert that tree into a JSON tree. But we probably have a tree structure somewhere in the database, the structure I saw most of the time to represent tree in a database is a record with an Id and a ParentId, so I'm going to use that as the representation of my tree in the database, but since we don't have any database, an In memory collection can serve our purpose, our collection is something like this:

C#
public class Cate
 {
     public int Id { get; set; }
     public int? ParentId { get; set; }
     public string Name { get; set; }
 }

var cats = new List<Cate>
         {
             new Cate {Id = 1, ParentId = null, Name = "First"},
             new Cate {Id = 2, ParentId = null, Name = "Second"},
             new Cate {Id = 3, ParentId = null, Name = "Thrid"},
             new Cate {Id = 4, ParentId = null, Name = "Fourth"},
             new Cate {Id = 5, ParentId = 4, Name = "SubFourth1"},
             new Cate {Id = 6, ParentId = 4, Name = "SubFourth2"},
             new Cate {Id = 7, ParentId = 5, Name = "Sub_SubFourth1"},
             new Cate {Id = 8, ParentId = null, Name = "Sixth"},
             new Cate {Id = 9, ParentId = null, Name = "Seventh"},
             new Cate {Id = 10, ParentId = 9, Name = "SubSeventh1"},
             new Cate {Id = 11, ParentId = 9, Name = "SubSeventh2"},
             new Cate {Id = 12, ParentId = null, Name = "Eighth"},
             new Cate {Id = 13, ParentId = null, Name = "Ninth"},
             new Cate {Id = 14, ParentId = null, Name = "Tenth"},
             new Cate {Id = 15, ParentId = null, Name = "Eleventh"},
             new Cate {Id = 16, ParentId = 15, Name = "SubEleventh"},
             new Cate {Id = 17, ParentId = 16, Name = "Sub_SubEleventh"},
         };

Now we have the data we need for building a tree. What we need next is a type to represent our tree, every tree consists of many nodes, so we need to describe our node here, our type would be something like this:

C#
class Node
    {
        [JsonProperty(PropertyName = "nodes")]
        public List<Node> Children = new List<Node>();

        public bool ShouldSerializeChildren()
        {
            return (Children.Count > 0);
        }

        //[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
        public Node Parent { get; set; }
        public int Id { get; set; }
        public int? ParentId { get; set; }

        [JsonProperty(PropertyName = "text")]
        public string Name { get; set; }
    }

To better understand our Node class, let's take a look at this tree image:

Every Node has a parent, so we declare a property of the type Node called Parent. In every Node, we have some data, which in this case is Id and ParentId and Name, and also, a Node can have many nodes as children, so we declared a property called Children that holds a list of Nodes as its children, and since we use Json.NET for our conversion form C# tree structure to JSON, ShouldSerializeChildren is responsible for something called "Conditional Property Serialization", we need this because if we had a Node Without Children, The default behavior of Json.NET is that it includes this in our tree as empty collection of Nodes like this: "nodes": [], and finally we have couple of Attributes that isn't doing anything here except changing the name of our property in serialization.

Second Step: Filling the Tree with Data

Now we have all the types necessary to build a simple tree, what we need to do now is to fill our tree structure with data, I've found a method for that here, and changed it slightly to fit my need:

C#
public IEnumerable<Node> RawCollectionToTree(List<Cate> collection)
   {
       var treeDictionary = new Dictionary<int?, Node>();

       collection.ForEach(x => treeDictionary.Add(x.Id,
                          new Node { Id = x.Id, ParentId = x.ParentId, Name = x.Name }));

       foreach (var item in treeDictionary.Values)
       {
           if (item.ParentId != null)
           {
               Node proposedParent;

               if (treeDictionary.TryGetValue(item.ParentId, out proposedParent))
               {
                   item.Parent = proposedParent;

                   proposedParent.Children.Add(item);
               }
           }

       }
       return treeDictionary.Values.Where(x => x.Parent == null);
   }

Here we've built a dictionary called treeDictionary and we filled this dictionary with our data, key of this dictionary will be the Id of our Cate type and the value will be the data of the node. After we filled our dictionary, it's time to assign the node's Parent and Children property to its corresponding Parent and Children in the dictionary, here we foreach through our dictionary and if our node had a ParentId, we go ahead and get that Parent, and assign it to our current node's (item) Parent property, and add to the Parent (proposedParent) its Children, which here is our Item, and return the dictionary where Parent is null, now we have a tree in C#:

Now we need to convert this tree to JSON.

Third Step: Converting C# Tree To JSON Tree

Last step and the easiest, is to convert our C# tree to JSON, but there are a couple of issues you might face, which I'll explain next, for conversion we use this code:

C#
var tree= roots.RawCollectionToTree(cats).ToList();

       string json = JsonConvert.SerializeObject(tree, Formatting.Indented,
           new JsonSerializerSettings
           {
               ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
               NullValueHandling = NullValueHandling.Ignore
           });

Here, we first use our RawCollectionToTree method to build a tree form our collection, then we convert it into JSON, there are two other things which might be worth pointing out, here we use a JsonSerializerSettings with two properties, the first ReferenceLoopHandling is responsible for ignoring the Self referencing looping, which can cause stackoverflow exception, and the second one which is kind of obvious is the null value serialization, we tell the serializer to ignore the null values. Now we have a JSON tree which resembles something like this:

C#
    [
  {
    "Id": 1,
    "text": "First"
  },
  {
    "Id": 2,
    "text": "Second"
  },
  {
    "Id": 3,
    "text": "Thrid"
  },
  {
    "nodes": [
      {
        "nodes": [
          {
            "Id": 7,
            "ParentId": 5,
            "text": "Sub_SubFourth1"
          }
        ],
        "Id": 5,
        "ParentId": 4,
        "text": "SubFourth1"
      },
      {
        "Id": 6,
        "ParentId": 4,
        "text": "SubFourth2"
      }
    ],
    "Id": 4,
    "text": "Fourth"
  },
  {
    "Id": 8,
    "text": "Sixth"
  },
  {
    "nodes": [
      {
        "Id": 10,
        "ParentId": 9,
        "text": "SubSeventh1"
      },
      {
        "Id": 11,
        "ParentId": 9,
        "text": "SubSeventh2"
      }
    ],
    "Id": 9,
    "text": "Seventh"
  },
  {
    "Id": 12,
    "text": "Eighth"
  },
  {
    "Id": 13,
    "text": "Ninth"
  },
  {
    "Id": 14,
    "text": "Tenth"
  },
  {
    "nodes": [
      {
        "nodes": [
          {
            "Id": 17,
            "ParentId": 16,
            "text": "Sub_SubEleventh"
          }
        ],
        "Id": 16,
        "ParentId": 15,
        "text": "SubEleventh"
      }
    ],
    "Id": 15,
    "text": "Eleventh"
  }
]

You can download the sample project from here.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Hamid Mosalla
Software Developer
Iran (Islamic Republic of) Iran (Islamic Republic of)
Programming is my passion, because I find it so intellectually rewarding. I currently work as a back-end web developer, using Microsoft technology stack, I also blog about my experiences and contribute to open source projects on my free time.

Comments and Discussions

 
QuestionGood Pin
Member 142222629-Apr-19 6:50
MemberMember 142222629-Apr-19 6:50 
PraiseGreat , concise and efficient Pin
Aqeel Ansari16-Feb-18 0:47
MemberAqeel Ansari16-Feb-18 0:47 
GeneralMy vote of 5 Pin
DumbRadish27-Mar-17 4:34
MemberDumbRadish27-Mar-17 4:34 
PraiseNice Article Pin
gijith6-Dec-16 21:52
professionalgijith6-Dec-16 21:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.