我有一个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
}
]}
答案 0 :(得分:5)
与您链接的示例一样,有两个主要任务。首先,我们需要将字典中的数据转换为分层形式。有一次,我们已经完成了,我们可以担心将其序列化为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
,如果名称是点(.
)
希望这有帮助。