将展平的分层数据转换为树形结构的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 bedroom
和Other
显示为从属于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
属性。
希望这可以帮助。