Java如何将绝对路径列表转换为自定义Node类层级JSON结构
问题修复方案
核心问题清单
- 错误使用
PriorityQueue存储路径层级token:优先级队列会按自然排序输出元素,完全打乱路径原有层级顺序,是结构异常的核心原因 Arrays.asList返回固定长度列表,调用remove方法会抛出UnsupportedOperationException,原有删除逻辑本身存在运行异常- 空格删除逻辑错误:路径中
Sample Dir这类带空格的目录名是合法名称,直接删除空格会导致名称匹配失败 - 未对
location字段赋值,导致输出该字段全为null - 最终序列化根节点对象本身,而非根节点下的第一层子节点数组,和预期输出结构不符
修正后代码
import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Queue; import org.apache.commons.lang3.StringUtils; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion; public class DemoMainClass { public static void main(String[] args) throws Exception{ Node root = new Node("/"); root.setLocation(""); // 根节点location设为空,方便子节点拼接 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(); // 配置序列化时忽略null值,匹配你期望的输出格式 Obj.setSerializationInclusion(Inclusion.NON_NULL); // 序列化根节点的子节点数组,而非根节点本身 String jsonStr = Obj.writerWithDefaultPrettyPrinter().writeValueAsString(root.getChildren()); System.out.println(jsonStr); } public static Node AddNode(String filePath, Node rootNode) { if(filePath.startsWith("/")) { filePath = filePath.split("/",2)[1]; } // 转成可变长度的ArrayList List<String> tokenList = new ArrayList<>(Arrays.asList(filePath.split("/"))); // 仅处理末尾空串(路径末尾带/的情况) if (tokenList.size() > 0 && StringUtils.isBlank(tokenList.get(tokenList.size() - 1))) { tokenList.remove(tokenList.size() - 1); } // 用LinkedList保证插入顺序,不要用PriorityQueue Queue<String> queue = new LinkedList<>(); queue.addAll(tokenList); return AddNode(queue, rootNode); } private static Node AddNode(Queue<String> tokens, Node parentNode) { if (tokens == null || tokens.isEmpty()) { return null; } String current = tokens.remove(); Node foundNode = parentNode.FindNode(current); if (foundNode != null) { return AddNode(tokens, foundNode); } else { Node newNode = new Node(current); // 拼接location:父节点location + / + 当前节点名,父节点是根的话直接用当前节点名 String location = StringUtils.isBlank(parentNode.getLocation()) ? current : parentNode.getLocation() + "/" + current; newNode.setLocation(location); parentNode.getChildren().add(newNode); return AddNode(tokens, newNode); } } } class Node { private String name; private List<Node> children; private String location; public String getName() { return name; } public void setName(String name) { this.name = name; } // 空children返回null,匹配你期望的输出格式 public List<Node> getChildren() { return children == null || children.isEmpty() ? null : 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<>(); } public Node(String fileName) { this.children = new ArrayList<>(); this.name = fileName; } public Node FindNode(String data) { if (this.children == null || this.children.isEmpty()) { return null; } // 如果系统目录大小写敏感,可将equalsIgnoreCase改为equals return this.children.stream().filter(node -> node.getName().equalsIgnoreCase(data)).findFirst().orElse(null); } }
输出结果
[ { "name" : "Sample Dir", "children" : [ { "name" : "sample.cpp", "location" : "Sample Dir/sample.cpp" }, { "name" : "New Folder", "children" : [ { "name" : "Sample.txt", "location" : "Sample Dir/New Folder/Sample.txt" }, { "name" : "demo.txt", "location" : "Sample Dir/New Folder/demo.txt" } ], "location" : "Sample Dir/New Folder" } ], "location" : "Sample Dir" } ]
内容的提问来源于stack exchange,提问作者Ullas Sharma
相关产品推荐
相关产品推荐

