Serializing a Tree into Json Object

前端 未结 2 1543
盖世英雄少女心
盖世英雄少女心 2021-01-03 09:30

I have the following classes:

TreeNode.cs

public class TreeNode : IEnumerable
{
    public readonly Dictionary

        
相关标签:
2条回答
  • 2021-01-03 09:59

    As I said in my comment, your TreeNode class is serialized as an array because it implements IEnumerable<TreeNode>. So the only thing you will ever see when a TreeNode is serialized, are the children of a node. These children are (of course) also serialized as an array - down to the last leaf node. The leaf nodes don't have children and are therefore serialized as empty arrays. So that's why your JSON output looks like this.

    You didn't exactly specify what JSON output you want to have, but I think what you want is like this:

    {
        "Sales Order": { },
        "RFP":
        {
            "2169": { }
        },
        "Purchase Order":
        {
            "2216": { }
        }
    }
    

    To achieve this, your TreeNode class must be serialized as object. In my opinion (and assuming/suggesting you're using Newtonsoft Json.NET), you should write a custom converter class which might look like this:

    class TreeNodeConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
        {
            // we can serialize everything that is a TreeNode
            return typeof(TreeNode).IsAssignableFrom(objectType);
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            // we currently support only writing of JSON
            throw new NotImplementedException();
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            // we serialize a node by just serializing the _children dictionary
            var node = value as TreeNode;
            serializer.Serialize(writer, node._children);
        }
    }
    

    Then you have to decorate your TreeNode class with the JsonConverterAttribute so the serializer knows that it has to use your converter when serializing a TreeNode object.

    [JsonConverter(typeof(TreeNodeConverter))]
    public class TreeNode : IEnumerable<TreeNode>
    {
        // ...
    }
    

    If you don't use Json.NET, I can't exactly tell you what to do but it might help if you would implement IDictionary instead of IEnumerable so the serializer knows you're dealing with key-value-pairs.

    0 讨论(0)
  • 2021-01-03 10:14

    I was preparing data from database for bootstrap treeview. And this worked for me:

    public class TreeNode {
        public string id { get; private set; }
    
        public string text { get; private set; }
    
        public bool selectable { get; private set; }
    
        public readonly Dictionary<string, TreeNode> nodes = new Dictionary<string, TreeNode>();
    
        [JsonIgnore]
        public TreeNode Parent { get; private set; }
    
        public TreeNode(
            string id,
            string text,
            bool selectable
        ) {
            this.id = id;
            this.text = text;
            this.selectable = selectable;
        }
    
        public TreeNode GetChild(string id) {
            var child = this.nodes[id];
            return child;
        }
    
        public void Add(TreeNode item) {
            if(item.nodes != null) {
                item.nodes.Remove(item.id);
            }
    
            item.Parent = this;
            this.nodes.Add(item.id, item);
        }
    }
    

    Buildng tree:

    var mapping = new Dictionary<string, TreeNode>(StringComparer.OrdinalIgnoreCase);
    
    foreach(var ln in mx) {
        // 
        var ID = (string)ln[0];
        var TEXT = (string)(ln[1]);
        var PARENT_ID = (string)(ln[2]);
    
        // 
        var node = new TreeNode(ID, TEXT, true);
    
        if(!String.IsNullOrEmpty(PARENT_ID) && mapping.ContainsKey(PARENT_ID)) {
            var parent = mapping[PARENT_ID];
            parent.Add(node);
        }
        else {
            tree.Add(node);
        }
        mapping.Add(ID, node);
    }
    
    var setting = new JsonSerializerSettings {
        Formatting = Formatting.Indented,
        NullValueHandling = NullValueHandling.Ignore,
        ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
    };
    
    // Ignore root element, just childs - tree.nodes.Values
    var json = JsonConvert.SerializeObject(tree.nodes.Values, setting);
    
    // Empty dictionary - remove (not needed for valid JSON)
    return json.ToString().Replace("\"nodes\": {},", "");
    
    0 讨论(0)
提交回复
热议问题