使用map超过1个深度级别,从csv转换为json
我有一个csv文件,其内容如下:
Fruit, Mango Fruit, Apple Car, Audi Apple, Red Color, Brown
我想最终以这样的格式转换它:
"hierarchy" : [{ "label": "Fruit", "children" : [ {label: "Mango"}, {label: "Apple", "children": [ {label:"Red"}]} ] }, { "label" : "Car", "children" : [ {label: "Audi"} ] }, { "label" : "Color", "children" : [ {label: "Brown"} ] }]
为此,我在地图中插入了值:
StringBuilder sb = new StringBuilder(); String line = br.readLine(); while (line != null) { sb.append(line); sb.append("\n"); line = br.readLine(); } String[] contents=(sb.toString().split("\n")); String[] newContents; Map<String, List> myMaps = new LinkedHashMap<String, List>(); for(String s : contents) { newContents= s.split(","); if (!myMaps.containsKey(newContents[0])) { myMaps.put(newContents[0], new ArrayList()); } myMaps.get(newContents[0]).add(newContents[1]); }
这基本上将文件转换为父(键)和子(值)forms的映射。 然而,我想知道如何处理超过1级深度的情况 – 例如在我给定的csv中? 地图是否适用于这种情况还是有更好的方法?
您的JSON结构看起来更像一棵树,可以被设计为一个类:
public class Node { private String label; private List children; // can also be of type Node[] // getters, setters }
那么层次结构是一个数组或节点列表
列表比arrays更受欢迎,因为它在儿童群体中更容易使用
更新:有关如何使用Node
类填充树的完整示例:
public class Node { private String label; private List children = new ArrayList<>(); // to avoid checks for null public String getLabel() { return label; } public void setLabel(String label) { this.label = label; } public List getChildren() { return children; } public void setChildren(List children) { this.children = children; } } class Converter { public List fromCsvFile(String filename) throws IOException { Node root = new Node(); BufferedReader input = new BufferedReader(new FileReader(filename)); String[] entry; String line = input.readLine(); while (line != null) { entry = line.split(","); // find or create Node node = findByLabel(root, entry[0]); if (node == null) { // top level node = new Node(); node.setLabel(entry[0]); root.getChildren().add(node); } // add child Node child = new Node(); child.setLabel(entry[1]); node.getChildren().add(child); // next line line = input.readLine(); } return root.getChildren(); } public Node findByLabel(Node node, String label) { if (label.equals(node.getLabel())) { return node; } for (Node child : node.getChildren()) { // recursion Node found = findByLabel(child, label); if (found != null) { return found; } } return null; } }
注意:您不需要显式Node
,并且可以使用Map
,其中值可以包含嵌套映射,或者子列表,或者标签的String值。 但使用显式类更清晰。
除了树中现有节点的递归查找之外,还可以创建一个独立的平面集合(Map)来加速查找:
class Converter { public List fromCsvFile(String filename) throws IOException { Node root = new Node(); Map existingNodes = new HashMap<>(); BufferedReader input = new BufferedReader(new FileReader(filename)); String[] entry; String line = input.readLine(); while (line != null) { entry = line.split(","); // find or create Node node = existingNodes.get(entry[0]); if (node == null) { // new top level node node = new Node(); node.setLabel(entry[0]); root.getChildren().add(node); existingNodes.put(entry[0], node); } // add child Node child = new Node(); child.setLabel(entry[1]); node.getChildren().add(child); existingNodes.put(entry[1], child); // next line line = input.readLine(); } return root.getChildren(); } }
仅供参考: 完整示例
地图很好。 只需使用递归函数来编写更深层次。
尝试这个。
String csv = "" + "Fruit, Mango\n" + "Fruit, Apple\n" + "Car, Audi\n" + "Apple, Red\n" + "Color, Brown\n" + "Red, Fire\n"; Set topLevels = new LinkedHashSet<>(); Set notTopLevels = new LinkedHashSet<>(); Map> labels = new LinkedHashMap<>(); try (BufferedReader reader = new BufferedReader(new StringReader(csv))) { String line; while ((line = reader.readLine()) != null) { String[] fields = line.split("\\s*,\\s*"); Map value = labels.computeIfAbsent( fields[1], k -> new LinkedHashMap()); labels.computeIfAbsent( fields[0], k -> new LinkedHashMap()) .put(fields[1], value); topLevels.add(fields[0]); notTopLevels.add(fields[1]); } } Map hierarchy = new LinkedHashMap<>(); topLevels.removeAll(notTopLevels); for (String s : topLevels) hierarchy.put(s, labels.get(s)); System.out.println(hierarchy);
结果:
{Fruit={Mango={}, Apple={Red={Fire={}}}}, Car={Audi={}}, Color={Brown={}}}