将展平的分层数据转换为树形结构的JSON

我有一个C#字典对象,其中包含该文件可用的文件和文件夹的名称。 我想将数据转换为分层树。 以下是数据。 如何将其转换为树形结构的JSON。

我调查了这个例子但是我无法获得所需的输出。

+-----------------------------------------------+| | Name | Path |------------------------------------------------| | Kitchen supplies | Shopping / Housewares | | Groceries | Shopping / Housewares | | Cleaning supplies | Shopping / Housewares | | Office supplies | Shopping / Housewares | | Retile kitchen | Shopping / Remodeling | | Ceiling | Shopping / Paint bedroom | | Walls | Shopping / Paint bedroom | | Misc | null | | Other | Shopping | +-----------------------------------------------+| 

应生成如下输出:

  {"text":".","children": [ { Name:' Shopping', children:[{ Name:'Housewares', children:[{ Name:'Kitchen supplies', leaf:true, },{ Name:'Groceries', leaf:true, },{ Name:'Cleaning supplies', leaf:true, },{ Name: 'Office supplies', leaf: true, }] }, { Name:'Remodeling', children:[{ Name:'Retile kitchen', leaf:true, },{ Name:'Paint bedroom', children: [{ Name: 'Ceiling', leaf: true }, { Name: 'Walls', iconCls: 'Name', }] }, { Name: 'Other', leaf: true }] }] }, { Name: 'Misc', leaf: true } ]} 

与您链接的示例一样,有两个主要任务。 首先,我们需要将字典中的数据转换为分层forms。 有一次,我们已经完成了,我们可以担心将其序列化为JSON。

首先,我们需要一个Node类来表示层次结构:

 class Node { public Node() { Children = new List(); } public string Name { get; set; } public List Children { get; set; } } 

一旦我们有了,我们就可以浏览字典并构建树。 (注意:在您想要的JSON中,您将Paint bedroomOther显示为从属于Remodeling ,而在您的示例字典数据中它们从属于Shopping 。我假设JSON在这种情况下是正确的,所以我相应地更改了字典数据如下所示。)

 Dictionary dict = new Dictionary(); dict.Add("Kitchen supplies", "Shopping / Housewares"); dict.Add("Groceries", "Shopping / Housewares"); dict.Add("Cleaning supplies", "Shopping / Housewares"); dict.Add("Office supplies", "Shopping / Housewares"); dict.Add("Retile kitchen", "Shopping / Remodeling"); dict.Add("Ceiling", "Shopping / Remodeling / Paint bedroom"); dict.Add("Walls", "Shopping / Remodeling / Paint bedroom"); dict.Add("Misc", null); dict.Add("Other", "Shopping / Remodeling"); Node root = new Node(); foreach (KeyValuePair kvp in dict) { Node parent = root; if (!string.IsNullOrEmpty(kvp.Value)) { Node child = null; foreach (string part in kvp.Value.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries)) { string name = part.Trim(); child = parent.Children.Find(n => n.Name == name); if (child == null) { child = new Node { Name = name }; parent.Children.Add(child); } parent = child; } } parent.Children.Add(new Node { Name = kvp.Key }); } 

现在我们有了树,我们可以序列化它。 但是,我们需要一些特殊处理,因为您的叶节点的呈现方式与JSON中的非叶节点不同:叶节点具有leaf属性且没有children属性,而非叶节点则相反。 要处理这个逻辑,我们需要一个自定义的JsonConverter 。 (只是为了澄清,我在这里使用Json.Net–你的问题没有提到特定的JSON序列化器。)

 class NodeConverter : JsonConverter { public override bool CanConvert(Type objectType) { return (objectType == typeof(Node)); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { Node node = (Node)value; JObject jo = new JObject(); jo.Add("name", node.Name); if (node.Children.Count == 0) { jo.Add("leaf", true); } else { jo.Add("children", JArray.FromObject(node.Children, serializer)); } jo.WriteTo(writer); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { throw new NotImplementedException(); } } 

我们可以使用JsonConverter将树序列化为JSON,如下所示:

 JsonSerializerSettings settings = new JsonSerializerSettings { Converters = new List { new NodeConverter() }, Formatting = Formatting.Indented }; string json = JsonConvert.SerializeObject(root, settings); Console.WriteLine(json); 

这是输出:

 { "name": ".", "children": [ { "name": "Shopping", "children": [ { "name": "Housewares", "children": [ { "name": "Kitchen supplies", "leaf": true }, { "name": "Groceries", "leaf": true }, { "name": "Cleaning supplies", "leaf": true }, { "name": "Office supplies", "leaf": true } ] }, { "name": "Remodeling", "children": [ { "name": "Retile kitchen", "leaf": true }, { "name": "Paint bedroom", "children": [ { "name": "Ceiling", "leaf": true }, { "name": "Walls", "leaf": true } ] }, { "name": "Other", "leaf": true } ] } ] }, { "name": "Misc", "leaf": true } ] } 

另一个小注意事项:在上面所需的JSON中,您将使用text属性而不是name属性显示根节点,该属性与所有其他节点不一致。 我假设这是一个错误。 如果不是,则需要更改JsonConverter,以便它具有输出text属性的逻辑,如果名称是点( . ),则输出text属性。

希望这可以帮助。