Вероятно, есть более сжатые и элегантные способы сделать это, но они должны быть достаточно устойчивыми к ошибкам, отсутствующим узлам и несортированным данным (см. Пример ввода ниже; я предполагаю, что вы можете прочитать файл, поэтому я начну список строк).
Для начала неплохо использовать org.json
или какую-нибудь другую библиотеку, чтобы не изобретать колесо и не разбираться с различными крайними случаями в процессе сериализации. Если вы имеете дело с простыми строками, какими кажетесь, это может быть выполнимо, но свертывание их самостоятельно должно быть последним средством. через путь, создавая Node
объекты для любых отсутствующих элементов и сохраняя их в ha sh с ключом по имени пути. Последние элементы в пути каждой строки - это листья, и им будут назначены свойства для этой строки, в то время как внутренние узлы ищут и добавляют потомков из ранее проанализированных узлов с помощью ha sh. Это создает связанную n-мерную древовидную структуру.
Следующим шагом является поиск root (мы утверждаем, что существует только один root) и запуск сериализатора JSON, начиная с листьев и рекурсивная передача сериализованных объектов обратно родителям.
Обратите внимание, что org.JSON
будет отсортировать ключи, но результат будет в такой же степени соответствовать JSON spe c, как и ваш ожидаемый результат, что гарантирует отсутствие упорядочения для свойства объекта.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import org.json.JSONArray;
import org.json.JSONObject;
class Node {
String name;
String type;
String property;
ArrayList<Node> children;
public Node(String name, String type, String property, ArrayList<Node> children) {
this.name = name;
this.type = type;
this.property = property;
this.children = children;
}
public JSONObject toJSON() {
JSONArray serializedChildren = new JSONArray();
for (Node child : children) {
serializedChildren.put(child.toJSON());
}
return new JSONObject()
.put("name", name)
.put("type", type)
.put("property", property)
.put("children", serializedChildren);
}
}
public class Main {
private static void validate(boolean cond, String msg) {
if (!cond) throw new IllegalArgumentException(msg);
}
private static void parseLine(HashMap<String, Node> nodes, String line) {
String[] tokens = line.split(", ");
validate(tokens.length == 3, "There must be 3 tokens per line");
String[] names = tokens[0].split("\\.");
validate(names.length != 0, "There must be at least one name in the path");
for (int i = names.length - 1; i >= 0; i--) {
String name = String.join(".", Arrays.copyOfRange(names, 0, i + 1));
Node node = nodes.get(name);
if (node == null) {
nodes.put(name, node = new Node(names[i], null, null, new ArrayList<>()));
}
if (i < names.length - 1) {
Node child = nodes.get(name + "." + names[i+1]);
validate(child != null, "Child lookup must succeed");
if (!node.children.contains(child)) {
node.children.add(child);
}
}
else {
node.type = tokens[1];
node.property = tokens[2];
}
}
}
public static HashSet<Node> parseNodes(List<String> lines) {
var nodes = new HashMap<String, Node>();
lines.forEach((line) -> parseLine(nodes, line));
for (Node node : nodes.values()) {
String[] tokens = node.name.split("\\.");
node.name = tokens[tokens.length-1];
}
return new HashSet<Node>(nodes.values());
}
public static Node findRoot(HashSet<Node> tree) {
var candidates = new HashSet<Node>(tree);
tree.forEach((node) -> candidates.removeAll(node.children));
validate(candidates.size() == 1, "There must be one root");
for (Node root : candidates) return root;
return null;
}
public static void main(String[] args) {
var lines = Arrays.asList(
"AAA.BBB.CCC, value3, value33",
"AAA.BBB.CCC.EEE.FFF, value5, value55",
"AAA.BBB, value3, value22",
"AAA, value1, value11",
"AAA.DDD, values44, value44"
);
Node root = findRoot(parseNodes(lines));
System.out.println(root.toJSON().toString(2));
}
}
Скомпилировано и выполнено с помощью:
javac -cp "json-20190722.jar" Main.java && java -cp "json-20190722.jar;." Main
Вывод:
{
"children": [
{
"children": [{
"children": [{
"children": [{
"children": [],
"name": "FFF",
"property": "value55",
"type": "value5"
}],
"name": "EEE"
}],
"name": "CCC",
"property": "value33",
"type": "value3"
}],
"name": "BBB",
"property": "value22",
"type": "value3"
},
{
"children": [],
"name": "DDD",
"property": "value44",
"type": "values44"
}
],
"name": "AAA",
"property": "value11",
"type": "value1"
}