Java 使用map将csv转换为json,深度超过1级
我有一个csv文件,其内容如下:Java 使用map将csv转换为json,深度超过1级,java,json,csv,hashmap,typeconverter,Java,Json,Csv,Hashmap,Typeconverter,我有一个csv文件,其内容如下: Fruit, Mango Fruit, Apple Car, Audi Apple, Red Color, Brown 我希望最终将其转换为如下格式: "hierarchy" : [{ "label": "Fruit", "children" : [ {label: "Mango"}, {label: "Apple", "children": [ {label:"Red"}]} ] }, { "label" : "Car", "c
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<String>> myMaps = new LinkedHashMap<String, List<String>>();
for(String s : contents)
{
newContents= s.split(",");
if (!myMaps.containsKey(newContents[0])) {
myMaps.put(newContents[0], new ArrayList<String>());
}
myMaps.get(newContents[0]).add(newContents[1]);
}
StringBuilder sb=新建StringBuilder();
String line=br.readLine();
while(行!=null){
某人附加(行);
某人附加(“\n”);
line=br.readLine();
}
字符串[]内容=(sb.toString().split(“\n”);
字符串[]newContents;
Map myMaps=新建LinkedHashMap();
for(字符串s:内容)
{
newContents=s.split(“,”);
如果(!myMaps.containsKey(newContents[0])){
put(newContents[0],newarraylist());
}
myMaps.get(newContents[0]).add(newContents[1]);
}
这将基本上将文件转换为父(键)和子(值)形式的映射。然而,我想知道当深度超过1级时,如何处理这种情况——例如在我给定的csv中?映射在这种情况下有效吗?还是有更好的方法?您的JSON结构看起来更像一棵树,可以设计为一个类:
public class Node {
private String label;
private List<Node> children; // can also be of type Node[]
// getters, setters
}
注意:您不需要显式的节点
,您可以使用映射
,其中值可以包含嵌套映射、子项列表或标签的字符串值。但是使用显式类更干净
除了递归查找树中的现有节点外,还可以创建独立的平面集合(Map)以加快查找速度:
class Converter {
public List<Node> fromCsvFile(String filename) throws IOException {
Node root = new Node();
Map<String, Node> 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();
}
}
类转换器{
CSVFile(字符串文件名)的公共列表引发IOException{
节点根=新节点();
Map existingNodes=new HashMap();
BufferedReader输入=新BufferedReader(新文件读取器(文件名));
字符串[]项;
String line=input.readLine();
while(行!=null){
条目=行分割(“,”);
//发现或创造
Node Node=existingNodes.get(条目[0]);
if(node==null){
//新的顶级节点
node=新节点();
node.setLabel(条目[0]);
root.getChildren().add(节点);
existingNodes.put(条目[0],节点);
}
//添加子项
节点子节点=新节点();
child.setLabel(条目[1]);
node.getChildren().add(子节点);
existingNodes.put(条目[1],子节点);
//下一行
line=input.readLine();
}
返回root.getChildren();
}
}
仅供参考:地图很好。只需使用递归函数来编写更深层次的代码 试试这个
String csv = ""
+ "Fruit, Mango\n"
+ "Fruit, Apple\n"
+ "Car, Audi\n"
+ "Apple, Red\n"
+ "Color, Brown\n"
+ "Red, Fire\n";
Set<String> topLevels = new LinkedHashSet<>();
Set<String> notTopLevels = new LinkedHashSet<>();
Map<String, Map<String, Object>> 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<String, Object> value = labels.computeIfAbsent(
fields[1], k -> new LinkedHashMap<String, Object>());
labels.computeIfAbsent(
fields[0], k -> new LinkedHashMap<String, Object>())
.put(fields[1], value);
topLevels.add(fields[0]);
notTopLevels.add(fields[1]);
}
}
Map<String, Object> hierarchy = new LinkedHashMap<>();
topLevels.removeAll(notTopLevels);
for (String s : topLevels)
hierarchy.put(s, labels.get(s));
System.out.println(hierarchy);
要映射键值对,只有
java.util.map
接口。或者您可以使用Library它将如何映射多个深度级别?您可以使用java.util.map
作为外部map
的值来生成此格式的JSON?(它可以用于深度为1的情况,但是如何创建一个级别可以超过2的贴图?。@TeeJay类似的例子that@TeeJay如果在CSV文件的较低记录中,顶级节点突然被称为另一个节点的子节点,则重新组织树仍然是一个挑战,此时,节点应从根节点
子节点移动到新节点子节点,这应在“添加子节点”逻辑之前完成。如果CSV上存在约束,则可以避免此操作,如按顺序提及子节点,对吗?(而不是下面记录中的其他地方?)例如:A、B/n A、C/n B、D/n C、E/n F、G。创建映射后,调用JSON序列化程序是否会将其转换为指定的JSON格式?@TeeJay是的,如果您已排序数据(根节点总是在其子节点之前提及),则不需要任何其他逻辑。许多库允许将JavaPOJO转换为JSON。节点
类是一个经典的POJO。看看杰克逊或格森图书馆。此外,如果您需要顶部的“hierarchy”属性,则应将返回的列表包装到其他对象中(使用属性hierarchy
的类,或使用键为“hierarchy”的单个条目进行映射)
String csv = ""
+ "Fruit, Mango\n"
+ "Fruit, Apple\n"
+ "Car, Audi\n"
+ "Apple, Red\n"
+ "Color, Brown\n"
+ "Red, Fire\n";
Set<String> topLevels = new LinkedHashSet<>();
Set<String> notTopLevels = new LinkedHashSet<>();
Map<String, Map<String, Object>> 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<String, Object> value = labels.computeIfAbsent(
fields[1], k -> new LinkedHashMap<String, Object>());
labels.computeIfAbsent(
fields[0], k -> new LinkedHashMap<String, Object>())
.put(fields[1], value);
topLevels.add(fields[0]);
notTopLevels.add(fields[1]);
}
}
Map<String, Object> 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={}}}