将扁平的分层数据转换为树状结构的 JSON
Posted
技术标签:
【中文标题】将扁平的分层数据转换为树状结构的 JSON【英文标题】:Converting flattened hierarchical data into a tree structured JSON 【发布时间】:2013-11-24 15:10:57 【问题描述】:我有一个 C# 字典对象,其中包含该文件可用的文件名和文件夹。我想将数据转换为分层树。下面是数据。如何将其转换为树状结构的 JSON。
我查看了这个example,但我无法获得所需的输出。
+-----------------------------------------------+|
| 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
]
【问题讨论】:
没有得到想要的输出是什么意思?出了什么问题? @Kuzgun:我不知道该怎么做。以及实现结果的最佳和最有效的方法是什么。 【参考方案1】:在您链接到的示例中,有两个主要任务。首先,我们需要将字典中的数据转换成分层的形式。一旦完成,我们就可以担心将其序列化为 JSON。
首先,我们需要一个Node
类来表示层次结构:
class Node
public Node()
Children = new List<Node>();
public string Name get; set;
public List<Node> Children get; set;
一旦我们有了它,我们就可以遍历字典并构建树。 (注意:在您想要的 JSON 中,您将 Paint bedroom
和 Other
显示为从属于 Remodeling
,而在您的示例字典数据中它们从属于 Shopping
。我假设 JSON 在这种情况下是正确的,所以我相应地更改了字典数据,如下所示。)
Dictionary<string, string> dict = new Dictionary<string, string>();
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<string, string> 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<JsonConverter> 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
属性,而不是名称为点 (.
) 时的 name
。
希望这会有所帮助。
【讨论】:
感谢您如此深入地回复示例。我不能要求更多。很棒的答案。以上是关于将扁平的分层数据转换为树状结构的 JSON的主要内容,如果未能解决你的问题,请参考以下文章
转换分层 DOM 树 XML 文件:XSLT 能否转换为“扁平化”XML 文件而不会丢失数据?