简体   繁体   中英

Convert string paths directory structure into to JSON object with Java

I am trying to create a nested tree view with Custom Pojo Node in Spring MVC, the input that I have from the JSch library after exec command1="find $(pwd) -maxdepth 1 -type f -not -path '*/\\.*' | sort" will be a list of Strings which contains Absolute Paths for files under the current working directory, as shown in the example below.

`List<String> paths = [
"/Sample Dir/sample.cpp",
"/Sample Dir/New Folder",
"/Sample Dir/New Folder/Sample.txt"];`

I need to create a hierarchical JSON object with the following Model:

public class Node {
    private String name;
    private String location;
    private List<Node> children;
    }

I'm trying to figure out the algorithm, how to represent file paths as a Node class which gives the below JSON. Below is the code which I tried, which is having some problems which i'm unable to figure out.

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.PriorityQueue;
import java.util.Queue;

import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.map.ObjectMapper;

public class DemoMainClass {

    public static void main(String[] args) throws Exception{
        Node root = new Node("/");
        AddNode("/Sample Dir/sample.cpp", root);
        AddNode("/Sample Dir/New Folder", root);
        AddNode("/Sample Dir/New Folder/Sample.txt", root);
        AddNode("/Sample Dir/New Folder/demo.txt", root);
        ObjectMapper Obj = new ObjectMapper(); 
        String jsonStr = Obj.writeValueAsString(root);
        System.out.println(jsonStr);
    }

    public static Node AddNode(String filePath, Node rootNode) {
        // convenience method. this creates the queue that we need for recursion from
        // the filepath for you
        if(filePath.startsWith("/")) {
            filePath = filePath.split("/",2)[1];
        }
        List<String> tokenList = Arrays.asList(filePath.split("/"));
        tokenList.remove(" ");
        // if you split a folder ending with / it leaves an empty string at the end and
        // we want to remove that
        if (StringUtils.isBlank(tokenList.get(tokenList.size() - 1))) {
            tokenList.remove(tokenList.size() - 1);
        }

        PriorityQueue<String> queue = new PriorityQueue<String>();
        queue.addAll(tokenList);
        return AddNode(queue, rootNode);
    }

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

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

        // 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(current);
            rootNode.getChildren().add(newNode);
            return AddNode(tokens, newNode);
        }
    }
}

class Node {
    public String name;
    public List<Node> children;
    public String location;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Node> getChildren() {
        return children;
    }

    public void setChildren(List<Node> children) {
        this.children = children;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }

    public Node() {
        this.children = new ArrayList<Node>();
    }
    
    public Node(String fileName) {
        this.children = new ArrayList<Node>();
        this.name = fileName;
    }
    public Node FindNode(String data) {
        if (this.children == null || this.children.isEmpty()) {
            return null;
        }
        // check Node list to see if there are any that already exist
        return this.children.stream().filter(node -> node.getName().equalsIgnoreCase(data)).findFirst().orElse(null);
        // .FirstOrDefault(n => n.Data.equalIgnoreCase(data));
    }

}



    

Below is the Output i'm getting:

{"name":"/","children":[{"name":"Sample Dir","children":[{"name":"sample.cpp","children":[],"location":null}],"location":null},{"name":"New Folder","children":[{"name":"Sample Dir","children":[{"name":"Sample.txt","children":[],"location":null},{"name":"demo.txt","children":[],"location":null}],"location":null}],"location":null}],"location":null}

Desired Output is as below,

 [
  {
    "name": "Sample Dir",
    "location": "Sample Dir",
    "children": [
      {
        "name": "New Folder",
        "location": "Sample Dir/New Folder",
        "children": [
          {
            "name": "Sample.txt",
            "location": "Sample Dir/New Folder/Sample.txt",
            "children": "null"
          }
        ]
      },
      {
        "name": "sample.cpp",
        "location": "Sample Dir/sample.cpp",
        "children": "null"
      }
    ]
  }
]

Could you help me to where I'm wrong? Any leads are appreciated, thanks in advance.

You're using PriorityQueue which will return the tokens in ascending order as no comparator is provided. In a priority queue the poll/remove method will remove the smallest element (depends on comparator) first. Instead you should use LinkedList which will work on FIFO principle. Update this

PriorityQueue<String> queue = new PriorityQueue<String>();

To this

Queue<String> queue = new LinkedList<>(tokenList);

This should give you the desired output except for the location for which the logic is missing.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM