es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Convertir la estructura de directorios de rutas de cadena en un objeto JSON con Java.

Estoy intentando crear una vista de árbol anidada con Custom Pojo Node en Spring MVC, la entrada que tengo de la biblioteca JSch después de ejecutar command1="find $(pwd) -maxdepth 1 -type f -not -path '*/\\.*' | sort" será una lista de Strings que contiene rutas absolutas de archivos bajo el directorio de trabajo actual, como se muestra en el ejemplo a continuación.

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

Necesito crear un objeto JSON jerárquico con el siguiente modelo:

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

Estoy tratando de averiguar el algoritmo, cómo representar las rutas de archivo como una clase Node que proporciona el siguiente JSON. A continuación se muestra el código que intenté, que tiene algunos problemas que no puedo solucionar.

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) {
        // Método de conveniencia. Esto crea la cola que necesitamos para la recursión a partir del archivo de ruta para usted
        if(filePath.startsWith("/")) {
            filePath = filePath.split("/",2)[1];
        }
        List<String> tokenList = Arrays.asList(filePath.split("/"));
        tokenList.remove(" ");
        // si divide una carpeta que termina con / deja una cadena vacía al final y queremos eliminar eso
        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) {
        // caso base -> el nodo no se encontró y se han ido los tokens :(
        if (tokens == null || tokens.isEmpty()) {
            return null;
        }

        // Obtener el token actual, dejando solo los que no se han buscado en el objeto tokens
        String current = tokens.remove();

        // crear el nodo si aún no existe
        Node foundNode = rootNode.FindNode(current);
        if (foundNode != null) {
            // el nodo existe! recursión
            return AddNode(tokens, foundNode);
        } else {
            // el nodo no existe! agréguelo manualmente y 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;
        }
        // compruebe la lista de nodos para ver si ya existen
        return this.children.stream().filter(node -> node.getName().equalsIgnoreCase(data)).findFirst().orElse(null);
    }
}

A continuación se muestra la salida que estoy obteniendo:

{"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}

El resultado deseado es el siguiente:

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

¿Podría ayudarme a ver dónde estoy equivocado? Se agradece cualquier ayuda, gracias de antemano.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Hay algunos problemas con el código que proporcionaste. Un problema es que el campo location en la clase Node nunca se establece en la ubicación real del archivo. En su lugar, siempre permanece null. Para solucionar este problema, puedes modificar el método AddNode para establecer el campo location de cada nodo en el valor apropiado.

    Otro problema es que el código no genera la salida JSON deseada. La salida JSON que proporcionaste tiene una estructura diferente en comparación con la salida que genera tu código. Para generar la estructura deseada, deberás modificar la clase Node para incluir un método que convierta el objeto Node a un Map o JsonObject.

    Aquí hay una implementación de ejemplo de la clase Node que incluye un método toJson:

    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    public class Node {
        private String name;
        private String location;
        private List<node> children = new ArrayList<>();
    
        public Node(String name, String location) {
            this.name = name;
            this.location = location;
        }
    
        public void addChild(Node child) {
            children.add(child);
        }
    
        public Map<string, object=""> toJson() {
            Map<string, object=""> map = new HashMap<>();
            map.put("name", name);
            map.put("location", location);
            if (!children.isEmpty()) {
                List<><string, object="">> childMapList = new ArrayList<>();
                for (Node child : children) {
                    childMapList.add(child.toJson());
                }
                map.put("children", childMapList);
            }
            return map;
        }
    }
    

    Aquí hay una implementación de ejemplo del método AddNode que establece el campo location y genera la salida deseada:

    public static Node addNode(String filePath, Node rootNode) {
        if (filePath.startsWith("/")) {
            filePath = filePath.substring(1);
        }
        String[] pathTokens = filePath.split("/");
        Node currentNode = rootNode;
        for (int i = 0; i < pathTokens.length; i++) {
            String token = pathTokens[i];
            Node childNode = currentNode.children.stream()
                    .filter(child -> child.name.equals(token))
                    .findFirst().orElse(null);
            if (childNode == null) {
                if (i == pathTokens.length - 1) {
                    // el último token es el nombre del archivo
                    childNode = new Node(token, filePath);
                } else {
                    // nodo de directorio intermedio
                    childNode = new Node(token, currentNode.location + "/" + token);
                }
                currentNode.addChild(childNode);
            }
            currentNode = childNode;
        }
        return rootNode;
    }
    
    public static void main(String[] args) throws Exception {
        List<string> paths = Arrays.asList(
                "/Sample Dir/sample.cpp",
                "/Sample Dir/New Folder",
                "/Sample Dir/New Folder/Sample.txt");
        Node root = new Node("/", "/");
        for (String path : paths) {
            addNode(path, root);
        }
        ObjectMapper obj = new ObjectMapper();
        List<><string, object="">> nodeList = new ArrayList<>();
        for (Node child : root.children) {
            nodeList.add(child.toJson());
        }
        String jsonStr = obj.writeValueAsString(nodeList);
        System.out.println(jsonStr);
    }
    

    Este código debería generar la salida JSON deseada:

    [
      {
        "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": []
              }
            ]
          },
          {
            "name": "sample.cpp",
            "location": "/Sample Dir/sample.cpp",
            "children": []
          }
        ]
      }
    ]
    

    ¡Espero que esto ayude! Hazme saber si tienes más preguntas.</string,></string,></string,></string,>

Comments are closed.