将目录路径转换为JSON目录树表示

3

我有一个文件路径的样本输出,这只是一个问题的例子。

New Text Document.txt
New folder/
New folder/README.txt

我希望将其转换为以下JSON格式:

{
   "Data":"/",
   "Nodes":[
      {
         "Data":"New Folder",
         "Nodes":[
            {
               "Data":"New Text Document.txt"
            }
         ]
      },
      {
         "Data":"New Text Document.txt",
         "Nodes":[
            ""
         ]
      }
   ]
} 

以下是我的Node类

public class Node
    {
        public Node(string fileName)
        {
            Nodes = new List<Node>();
            Data = fileName;
        }

        public List<Node> Nodes { get; set; }

        public string Data { get; set; }
    }

我正在尝试弄清楚如何用Node类表示文件路径,然后将其序列化为JSON。如果还有其他方法可以将文件路径表示为目录树结构的JSON,请建议。


1
你应该在问题中更清楚地表明那是问题所在。 - MarcinJuraszek
应该能够在字符'/'上拆分路径字符串,然后遍历每个标记,如果不存在,则创建子节点。 - Brad C
1
你以前用过递归吗? :) 我可以很快写一个例子。 - Brad C
有点用,谢谢提醒 :)) 我真的很感激关于这个问题的例子。 - mr. Holiday
你使用的是哪个 .NET 版本? - Dreamweaver
显示剩余4条评论
2个回答

5

我终于为你制作了一个示例。这应该是一个很好的可扩展递归解决方案。 :)

static void Main(string[] args)
{
    Node root = new Node("/");
    AddNode("New Text Document.txt", root);
    AddNode("New folder/", root);
    AddNode("New folder/README.txt", root);

    Console.ReadKey();
}

public class Node
{
    public Node() { Nodes = new List<Node>(); }
    public Node(string fileName)
    {
        Nodes = new List<Node>();
        Data = fileName;
    }

    public Node FindNode(string data)
    {
        if (this.Nodes == null || !this.Nodes.Any()) { return null; }

        // check Node list to see if there are any that already exist
        return this.Nodes
            .FirstOrDefault(n => String.Equals(n.Data, data, StringComparison.CurrentCultureIgnoreCase));
    }

    public string Data { get; set; }
    public List<Node> Nodes { get; set; }
}

public static Node AddNode(string filePath, Node rootNode)
{
    // convenience method. this creates the queue that we need for recursion from the filepath for you
    var tokens = filePath.Split('/').ToList();

    // if you split a folder ending with / it leaves an empty string at the end and we want to remove that
    if (String.IsNullOrWhiteSpace(tokens.Last())) { tokens.Remove(""); }

    return AddNode(new Queue<string>(tokens), rootNode);
}

private static Node AddNode(Queue<string> tokens, Node rootNode)
{
    // base case -> node wasnt found and tokens are gone  :(
    if (tokens == null || !tokens.Any())
    {
        return null;
    }

    // get current token, leaving only unsearched ones in the tokens object
    string current = tokens.Dequeue();

    // create node if not already exists
    Node foundNode = rootNode.FindNode(current);
    if (foundNode != null)
    {
        // node exists! recurse
        return AddNode(tokens, foundNode);
    }
    else
    {
        // node doesnt exist! add it manually and recurse
        Node newNode = new Node() { Data = current };
        rootNode.Nodes.Add(newNode);
        return AddNode(tokens, newNode);
    }
}

谢谢 :) 这就是我在寻找的。 - mr. Holiday

1
using System.Web.Script.Serialization; ///name space to use

    JavaScriptSerializer js = new JavaScriptSerializer();
      string json = js.Serialize(pass node class object here);

以下代码应该提供所需的目录结构。
static void Main(string[] args)
{
    string path = @"path where to check";
    Node n = new Node();
    n.Nodes = new List<Node>();
    GetNodes(path, n);
    JavaScriptSerializer js = new JavaScriptSerializer();
    string json = js.Serialize(n);
}

public static void GetNodes(string path, Node node)
{
    if (File.Exists(path))
    {
        node = new Node(path);
    }
    else if (Directory.Exists(path))
    {
        node.Data = "\\";
        GetFiles(path, node);

        foreach ( string item in Directory.GetDirectories(path))
        {
            Node n = new Node();
            n.Nodes = new List<Node>();
            n.Data = item;
            GetFiles(path, n);
            node.Nodes.Add(n);
        }
    }
}

public static void GetFiles(string path, Node node)
{
    foreach (string item in Directory.GetFiles(path))
    {
        node.Nodes.Add(new Node(item));
    }

}

public class Node
{
    public Node()
    { }
    public Node(string fileName)
    {
        Nodes = new List<Node>();
        Data = fileName;
    }

    public List<Node> Nodes { get; set; }

    public string Data { get; set; }
}

问题不在于对象序列化。问题在于如何将字符串路径转换为节点对象。 - mr. Holiday
纯粹为了这个例子,这里没有算法。 Node root = new Node("/"); root.Nodes.Add(new Node("New Text Document.txt")); root.Nodes.Add(new Node("New Folder")); root.Nodes[0].Nodes.Add(new Node("New Text Document.txt")); 如果我像你所说的那样序列化Node对象,我将得到我想要的结果。 - mr. Holiday
这不完全是我要找的。我不能使用Directory类,因为我正在处理zip文件,但我会尝试重写你的代码,谢谢。 - mr. Holiday
很好的代码;它可以工作,但需要安装一个引用:System.Web.Extensions - Marcelo Scofano Diniz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接