2013-04-30 55 views
2

我有以下类别:序列化树成JSON对象

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. 
} 

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

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

在序列化的时候,树看起来是这样的:

Tree

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

+0

我认为序列化程序查看对象的属性,所以请尝试在属性中包装_childs字典。 – Christian 2013-04-30 08:29:53

+1

问题是你的'TreeNode'类实现'IEnumerable ',因此序列化器会将你的节点序列化为一个数组(你的情况为空)。如果没有看到你的'IEnumerable'实现代码,我不知道它为什么是空的。 – fero 2013-04-30 08:32:00

+0

我已经添加了整个TreeNode类。 – mridula 2013-04-30 08:41:39

回答

1

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

你没有确切指定你想拥有什么JSON输出,但我想你想要的是这样的:

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

要做到这一点,您TreeNode类必须序列化为对象。在我看来(假定/建议你使用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如此串行器知道它在序列化一个对象时必须使用你的转换器。

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

如果你不使用Json.NET,我不能确切地告诉你做什么,但它可能会帮助,如果你将实现IDictionary代替IEnumerable所以串行知道你处理键 - 值对。

+0

我只是删除IEnumerable,因为它不是真的需要..它现在工作..非常感谢!虽然,我不明白为什么数组内的对象没有被序列化。 – mridula 2013-04-30 10:08:57

+0

他们确实被序列化了。但是它们被序列化为包含子节点的数组,这些节点也被序列化为数组等等。所以你不会得到任何东西,但数组。最后的子节点(叶节点)不包含任何子节点,所以它们被序列化为空数组。它们不能被序列化为其他任何东西(比如ID),因为它们必须是数组。 – fero 2013-04-30 10:49:50