3

I have the following classes:

TreeNode.cs

public class TreeNode : IEnumerable<TreeNode>
{
    public readonly Dictionary<string, TreeNode> _children = new Dictionary<string, TreeNode>();

    public readonly string Id;
    public TreeNode Parent { get; private set; }

    public TreeNode(string id)
    {
        this.Id = id;
    }

    public TreeNode GetChild(string id)
    {
        return this._childs[id];
    }

    public void Add(TreeNode item)
    {
        if (item.Parent != null)
        {
            item.Parent._childs.Remove(item.Id);
        }

        item.Parent = this;
        this._childs.Add(item.Id, item);
    }

    public IEnumerator<TreeNode> GetEnumerator()
    {
        return this._childs.Values.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return this.GetEnumerator();
    }

    public int Count
    {
        get { return this._childs.Count; }
    }
}

FolderStructureNode.cs

public class FolderStructureNode : TreeNode
{
    //Some properties such as FolderName, RelativePath etc.
}

So, when I have an object of type FolderStructureNode it is essentially a tree datastructure where each node represents a folder. I want to serialize this object into a JsonObject. I have tried both - JavaScriptSerializer and NewtonSoft. In both cases I get an output as -

[
  [
    []
  ],
  [
    []
  ],
  []
]

At the time of serialization, the tree looks something like this:

Tree

How do I serialize it in order to get the correct json object? Do I have to traverse the tree and create the json myself?

4

2 回答 2

3

正如我在评论中所说,您的TreeNode类被序列化为一个数组,因为它实现了IEnumerable<TreeNode>. 因此,当 a 被序列化时,您唯一会看到的TreeNode是节点的子节点。这些孩子(当然)也被序列化为一个数组 - 一直到最后一个叶节点。叶节点没有子节点,因此被序列化为空数组。这就是为什么您的 JSON 输出看起来像这样的原因。

您没有确切指定您想要的 JSON 输出,但我认为您想要的是这样的:

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

为此,您的TreeNode类必须序列化为object。在我看来(并假设/建议您使用 Newtonsoft Json.NET),您应该编写一个可能如下所示的自定义转换器类:

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

然后你必须用 来装饰你的TreeNode类,JsonConverterAttribute这样序列化器就知道在序列化TreeNode对象时它必须使用你的转换器。

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

如果您不使用 Json.NET,我无法准确告诉您该怎么做,但如果您实施IDictionary而不是IEnumerable让序列化程序知道您正在处理键值对,这可能会有所帮助。

于 2013-04-30T09:18:23.110 回答
0

我正在从数据库中为bootstrap treeview准备数据。这对我有用:

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

建筑树:

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\": {},", "");
于 2019-08-30T07:29:50.653 回答