【问题标题】:Convert a Treeview to JSON using C#使用 C# 将 Treeview 转换为 JSON
【发布时间】:2019-09-09 16:38:38
【问题描述】:

我必须使用 C# 将 TreeView 对象转换为 JSON。我目前正在使用JsonConvert.SerializeObject()

public class SubTreeNode : TreeNode
{
    public CustomProperties customProperties;
}

public class CustomProperties
{

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

当用JsonConvert.SerializeObject(treeView1.Nodes); 尝试它时,它只返回顶部节点......而不是子节点、子节点等。

序列化和反序列化此 TreeView 对象的最简单方法是什么?

【问题讨论】:

  • 当您致电SerializeObject() 时会发生什么?您是否得到了意想不到的结果?

标签: c# json treeview json.net


【解决方案1】:

您需要添加从每个节点递归生成 JSON 的方法。

查看相关帖子:Serializing a Tree into Json Object

【讨论】:

    【解决方案2】:

    我遇到了同样的问题:只有顶级节点使用标准 JSON.Net 序列化程序导出,因为正如上面链接下的 fero 正确指出的那样,“您的 TreeNode 类被序列化为数组,因为它实现了 IEnumerable”。它进一步说你应该用 JsonConverterAttribute 装饰 TreeNode 类。我没有让这个工作。

    这是另一种选择。请注意,这可能不是最好的方式。但这很简单:

    • 您正在使用标准 TreeNode 类,并且您的数据存储在 TreeView 中
    • 你想使用 JSON.NET 序列化器

    使用您要以 JSON 格式导出的信息创建一个新的分层类(在我的情况下,我只想导出部分树节点属性,因此创建一个新的简单类两次有意义):

    '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
    

    递归地将您的数据从 TreeView 移动到新的 JTree(我们的自定义类):

    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
    

    使用 JSON.NET 序列化器将简化的 JSON 树写入文件:

    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
    

    最终文本(示例):

    {
      "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
    }
    

    【讨论】:

      【解决方案3】:

      这是我的解决方案:


      1. 首先我创建一个节点类,其中包含我想要的节点数据结构,以及一个序列化对象的 JSon 方法

        [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. 我编写了一个可以递归调用的方法。这将返回给定特定树节点的子节点列表

            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. 我编写并更新了对象方法来创建一个根节点,我可以在其中包含树视图的所有节点。我决定使用根节点而不是节点列表,因为列表没有序列化对象的 JSon 方法。

        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. 根对象必须声明为单个节点

        private node root;
        

        你可以调用root的JSon方法

        MessageBox.show(root.JSon());
        

      希望对你有帮助

      【讨论】:

        【解决方案4】:

        使用自定义 json 序列化程序对我有用

        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();
            }
        }
        

        【讨论】:

        • 不应该是OrgChartConverter&lt;T&gt;吗?否则转换器怎么知道TNode&lt;T&gt; 中是什么?此外,您可能应该在答案中显示 Node&lt;T&gt; 类的定义。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-10-27
        • 1970-01-01
        • 2016-06-16
        • 2012-06-05
        • 2019-05-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多