我有以下课程:
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。在这两种情况下,我都得到一个输出 -
[
[
[]
],
[
[]
],
[]
]
在序列化时,树看起来像这样:
如何序列化以获取正确的json对象?我是否必须遍历树并自己创建json?
答案 0 :(得分:1)
正如我在评论中所说,您的TreeNode
类被序列化为数组,因为它实现了IEnumerable<TreeNode>
。因此,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
可能会有所帮助,因此序列化器知道您是处理键值对。
答案 1 :(得分: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);
}
}
Buildng树:
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\": {},", "");