此问题中的代码生成以下JSON。
代码应该通过行.Where(a => a.Values != null)
排除空的“子”键,但它不起作用。
我可以在哪里放置where子句,以便JSON不包含一堆空的“Children”数组?
感谢您的帮助。
[{
"NodeID" : 1,
"NodeText" : "Country",
"Children" : [{
"NodeID" : 3,
"NodeText" : "President",
"Children" : []
}, {
"NodeID" : 4,
"NodeText" : "Population",
"Children" : []
}, {
"NodeID" : 5,
"NodeText" : "State",
"Children" : [{
"NodeID" : 6,
"NodeText" : "Governor",
"Children" : []
}, {
"NodeID" : 7,
"NodeText" : "Population",
"Children" : []
}, {
"NodeID" : 8,
"NodeText" : "County",
"Children" : [{
"NodeID" : 9,
"NodeText" : "Population",
"Children" : []
}
]
}
]
}
]
}, {
"NodeID" : 2,
"NodeText" : "Year",
"Children" : []
}
]
以下是生成上述JSON的示例代码:
public class Node
{
public int? ParentNodeID { get; set; }
public int NodeID { get; set; }
public string NodeText { get; set; }
public Node(int? parentNodeID, int nodeID, string nodeText)
{
ParentNodeID = parentNodeID;
NodeID = nodeID;
NodeText = nodeText;
}
}
public List<Dictionary<string, object>> BuildTree(int? parentNodeID = null, List<Node> exampleData = null)
{
// kickstart the recursion with example data
if (exampleData == null)
{
exampleData = new List<Node>();
exampleData.Add(new Node(null, 1, "Country"));
exampleData.Add(new Node(null, 2, "Year"));
exampleData.Add(new Node(1, 3, "President"));
exampleData.Add(new Node(1, 4, "Population"));
exampleData.Add(new Node(1, 5, "State"));
exampleData.Add(new Node(5, 6, "Governor"));
exampleData.Add(new Node(5, 7, "Population"));
exampleData.Add(new Node(5, 8, "County"));
exampleData.Add(new Node(8, 9, "Population"));
}
List<Dictionary<string, object>> result = new List<Dictionary<string, object>>();
var nodes = exampleData.Where(a => a.ParentNodeID == parentNodeID).ToList();
if (nodes != null)
{
result.AddRange(nodes
.Select(a => new Dictionary<string, object> {
{ "NodeID", a.NodeID},
{ "NodeText", a.NodeText },
{ "Children", BuildTree(a.NodeID, exampleData) }
})
.Where(a => a.Values != null) // this doesn't have any effect
.ToList()
);
}
return result;
}
答案 0 :(得分:2)
问题在于,即使没有孩子,您也总是创建一个包含值“Children”的词典。
解决方法是将其置于一个条件中,如果没有子节点则不添加值,否则无论如何都不断添加带有空集合值的Children Key。
以下代码对我来说是完成此任务的:肉和土豆是Func<T> getNodeDictionary
,它现在在递归语句中被调用。
public static List<Dictionary<string, object>> BuildTree(int? parentNodeID = null, List<Node> exampleData = null)
{
// kickstart the recursion with example data
if (exampleData == null)
{
exampleData = new List<Node>();
exampleData.Add(new Node(null, 1, "Country"));
exampleData.Add(new Node(null, 2, "Year"));
exampleData.Add(new Node(1, 3, "President"));
exampleData.Add(new Node(1, 4, "Population"));
exampleData.Add(new Node(1, 5, "State"));
exampleData.Add(new Node(5, 6, "Governor"));
exampleData.Add(new Node(5, 7, "Population"));
exampleData.Add(new Node(5, 8, "County"));
exampleData.Add(new Node(8, 9, "Population"));
}
List<Dictionary<string, object>> result = new List<Dictionary<string, object>>();
var nodes = exampleData.Where(a => a.ParentNodeID == parentNodeID).ToList();
if (nodes != null)
{
Func<Node, Dictionary<string, object>> getNodeDictionary = n => {
var children = BuildTree(n.NodeID, exampleData); // still recursive
var returnDictionary = new Dictionary<string, object> { // these 2 nodes always get added
{ "NodeID", n.NodeID},
{ "NodeText", n.NodeText }
};
// This ensures we only add Children if there are actually any children
if (children.Any())
{
returnDictionary.Add("Children", children);
}
return returnDictionary;
};
// No need for where clause since we now do not add the empty elements
result.AddRange(nodes
.Select(a => getNodeDictionary(a))
.ToList()
);
}
return result;
}
答案 1 :(得分:0)
Values
中的{p> .Where(a => a.Values != null)
对于孩子来说始终不为空,因为您在递归({ "Children", BuildTree(a.NodeID, exampleData) }
)中正在使用它。改变检查空子的条件。
您可以添加方法:
private static bool IsNotEmptyTree(object value)
{
if (value == null) return false; //Is empty whatever
if (value as List<Dictionary<string, object>> != null)
{
var dict = (value as List<Dictionary<string, object>>);
return dict.Count > 0;
}
// not empty
return true;
}
并在Where:
中使用它.Where(a => a.Values.All(IsNotEmptyTree))
答案 2 :(得分:0)
想想这里发生了什么。你有:
result.AddRange(nodes
.Select(a => new Dictionary<string, object> {
{ "NodeID", a.NodeID},
{ "NodeText", a.NodeText },
{ "Children", BuildTree(a.NodeID, exampleData) }
})
.Where(a => a.Values != null) // this doesn't have any effect
.ToList()
);
Where
正在检查您创建的新项目,而不是节点。所以就像说:
var temp1 = nodes.Select(a => new Dictionary<string, object> { ... });
var temp2 = temp1.Where(a => a.Values != null);
result.AddRange(temp2);
所以temp1
是一堆匿名对象实例,所有这些实例都包含一个包含三个键/值对的字典。
我认为你想要的是:
.Where(a => a["Children"] != null)
当然,假设BuildTree
为空列表返回null
。