简体   繁体   中英

Convert a Treeview to JSON using C#

I have to convert a TreeView object to JSON using C#. I am currently using JsonConvert.SerializeObject() .

public class SubTreeNode : TreeNode
{
    public CustomProperties customProperties;
}

public class CustomProperties
{

    public string property1 = "Property1";
    public string property2 = "Property2";
    public string property3 = "Property3";
}

When tried it with JsonConvert.SerializeObject(treeView1.Nodes); it only returned the top nodes... not the child nodes, sub-child, and so on.

What is the easiest way to serialize and deserialize this TreeView object?

You will need to add methods that produce JSON from each node recursively.

Check out the related post: Serializing a Tree into Json Object .

I was confronted with the same problem: only top nodes are exported with the standard JSON.Net Serializer because, as fero under the above link rightly states, "your TreeNode class is serialized as an array because it implements IEnumerable". It further says you should decorate the TreeNode class with the JsonConverterAttribute. I didn't get this to work.

Here is an alternative. Please note that this may not be seen as the best way to do it. But it is pretty simple:

  • you are using standard TreeNode class and your data is stored in a TreeView
  • you want to use JSON.NET Serializer

Create a new hierarchical class with the information you want to export in JSON (in my case, I only want to export part of my treenode-properties, so creating a new simple class made sense twice):

'Simplified version of tree for json
'Compared to TreeNode class, this object is also serializable with the standard JSON.NET Serializer
Public Class JTree
    Public children As New List(Of JTree)()
    Private _name As String
    Public Property name() As String
        Get
            Return _name
        End Get
        Set(value As String)
            _name = value
        End Set
    End Property
    Private _id As String
    Public Property id() As String
        Get
            Return _id
        End Get
        Set(value As String)
            _id = value
        End Set
    End Property
End Class

Recursively move your data from TreeView to a new JTree (our custom class):

Public Sub createSimplifiedJSONTree(parentNode As TreeNode, ByRef JTreeSimp As JTree)
    'Start recursion on all subnodes
    For Each childNode As TreeNode In parentNode.Nodes
        Dim jchild As New JTree
        jchild.id = childNode.Name
        jchild.name = childNode.Text
        JTreeSimp.children.Add(jchild)
        createSimplifiedJSONTree(childNode, jchild)
    Next
End Sub

Write simplified JSON tree to file using JSON.NET Serializer:

Private Sub WriteJSONfromTreeview()
    Dim rootNode As TreeNode = TreeView1.Nodes(0)
    Dim JTreeSimp As New JTree
    createSimplifiedJSONTree(rootNode, JTreeSimp)

    'serialize JSON directly to a file using JSON.Net Serializer
    Using file__1 As StreamWriter = File.CreateText("c:\temp\test.txt")
        Dim serializer As New JsonSerializer()
        serializer.Formatting = Formatting.Indented
        serializer.Serialize(file__1, JTreeSimp)
    End Using
End Sub

Final txt (example):

{
  "children": [    
    {
      "children": [
        {
          "children": [
            {
              "children": [
                {
                  "children": [
                    {
                      "children": [
                        {
                          "children": [
                            {
                              "children": [],
                              "name": "alcatraz",
                              "id": "021_3",
                              "size": 166
                            }
                          ],
                          "name": "skyline",
                          "id": "031_3",
                          "size": 167
                        }
                      ],
                      "name": "city",
                      "id": "041_5",
                      "size": 167
                    }
                  ],
                  "name": "coit",
                  "id": "051_4",
                  "size": 169
                }
              ],
              "name": "tower",
              "id": "061_3",
              "size": 170
            }
          ],
          "name": "telegraphhill",
          "id": "071_3",
          "size": 170
        }
      ],
      "name": "coittower",
      "id": "081_2",
      "size": 170
    },   
    {
      "children": [
        {
          "children": [],
          "name": "sunset",
          "id": "071_112",
          "size": 3
        }
      ],
      "name": "berkeley",
      "id": "081_109",
      "size": 3
    },
    {
      "children": [
        {
          "children": [],
          "name": "marin",
          "id": "071_77",
          "size": 3
        }
      ],
      "name": "marinheadlands",
      "id": "081_110",
      "size": 3
    }
  ],
  "name": "root",
  "id": "000",
  "size": 0
}

This is my solution:


  1. First I create a node class that contains the data structure I want for the nodes, and a JSon method that serialize the object

     [JsonObject(ItemNullValueHandling = NullValueHandling.Ignore)] private class node { public node() { this.children = new List<node>(); } public node(string _value, List<node> _children = null, bool _isChecked = false) { Value = _value; isChecked = _isChecked; if (_children != null) { children = _children; } } [JsonProperty("value")] public string Value { get; set; } [JsonProperty("isChecked")] public bool isChecked { get; set; } [JsonProperty("children", NullValueHandling = NullValueHandling.Ignore)] public List<node> children { get; set; } [JsonIgnore] public string JSon { get { return JsonConvert.SerializeObject(this); } } } 

  1. I wrote a method that it's meant to be called recursively. This returns a list of the children nodes given a particular tree node

      private List<node> RunNode(TreeNode node) { List<node> nodeOut = new List<node>(); foreach(TreeNode child in node.Nodes) { List<node> grandchild = RunNode(child); nodeOut.Add(new node(child.Text, grandchild, child.Checked)); } return nodeOut; } 

  1. I wrote and update object method to create a root node where I can contain all the nodes of the treeview. I decided to use a root node instead of a list of nodes, because a list wouldn't have the JSon method that serialize the object.

     private void ActualizarMenus() { List<node> parents= new List<node>(); foreach (TreeNode node in trw.Nodes) { List<node> childs = RunNode(node); parents.Add(new node(node.Text,childs,node.Checked)); } root = new node("root", parents, true); } 
  2. The root object must be declared as a single node

     private node root; 

    and you can just call the JSon method of root

     MessageBox.show(root.JSon()); 

I hope this helps

using custom json serializer worked for me

var settings = new JsonSerializerSettings
                {
                    Converters = new List<JsonConverter> { new OrgChartConverter() },
                    Formatting = Formatting.Indented
                };

                string json = JsonConvert.SerializeObject(tree, settings);

public class OrgChartConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(Node<T>).IsAssignableFrom(objectType);
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        Node<T> node = (Node<T>)value;
        JObject obj = new JObject();
        obj.Add("Name", node.Value.Name);
        obj.Add("Children", JArray.FromObject(node.Children, serializer));
        obj.WriteTo(writer);
    }

    public override bool CanRead
    {
        get { return false; }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

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