将树序列化为 Json 对象 [英] Serializing a Tree into Json Object

查看:27
本文介绍了将树序列化为 Json 对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下课程:

TreeNode.cs

公共类 TreeNode : IEnumerable{public readonly Dictionary_children = new Dictionary();公共只读字符串 ID;公共树节点父{得到;私人订制;}公共树节点(字符串 id){this.Id = id;}公共 TreeNode GetChild(string id){返回 this._childs[id];}公共无效添加(树节点项){if (item.Parent != null){item.Parent._childs.Remove(item.Id);}item.Parent = this;this._childs.Add(item.Id, item);}公共 IEnumerator获取枚举器(){返回 this._childs.Values.GetEnumerator();}IEnumerator IEnumerable.GetEnumerator(){返回 this.GetEnumerator();}公共整数计数{得到 { 返回 this._childs.Count;}}}

FolderStructureNode.cs

public class FolderStructureNode : TreeNode{//一些属性,如FolderName、RelativePath等.}

所以,当我有一个 FolderStructureNode 类型的对象时,它本质上是一个树数据结构,其中每个节点代表一个文件夹.我想将此对象序列化为 JsonObject.我已经尝试过 - JavaScriptSerializer 和 NewtonSoft.在这两种情况下,我得到的输出为 -

<预><代码>[[[]],[[]],[]]

在序列化时,树看起来像这样:

如何序列化它以获得正确的 json 对象?我是否必须遍历树并自己创建 json?

解决方案

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

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

<代码>{销售订单": { },RFP":{2169":{}},采购订单":{2216":{}}}

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

class TreeNodeConverter : JsonConverter{public override bool CanConvert(Type objectType){//我们可以序列化所有属于 TreeNode 的东西返回 typeof(TreeNode).IsAssignableFrom(objectType);}公共覆盖对象 ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer){//我们目前只支持写入 JSON抛出新的 NotImplementedException();}public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer){//我们通过序列化_children 字典来序列化一个节点var node = 作为 TreeNode 的值;serializer.Serialize(writer, node._children);}}

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

[JsonConverter(typeof(TreeNodeConverter))]公共类 TreeNode : IEnumerable{//...}

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

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:

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?

解决方案

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.

这篇关于将树序列化为 Json 对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆