2

此问题中的代码生成以下 JSON。

代码应该通过 line 排除空的“Children”键.Where(a => a.Values != null),但它不起作用。

我可以在哪里放置 where 子句,以便 JSON 不包含一堆空的“儿童”数组?

谢谢你的帮助。

[{
        "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;
}
4

3 回答 3

2

问题是您总是在创建一个包含“儿童”值的字典,即使没有儿童也是如此。

解决方案是将其放入一个条件中,如果没有孩子则不添加该值,否则无论如何您都会继续添加带有空集合值的 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;
    }
于 2013-03-08T20:40:51.737 回答
0

Values对于孩子, in.Where(a => a.Values != null)始终不为空,因为您在递归 ( { "Children", BuildTree(a.NodeID, exampleData) }) 中初始化它。更改 Where 条件以检查空子。

您可以添加方法:

    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))
于 2013-03-08T19:49:58.610 回答
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一个空列表。

于 2013-03-08T20:19:33.693 回答