将数组转换为分层 JSONArray

Convert an array to hierarchical JSONArray

假设我有一个代表包结构的字符串数组。 它看起来像这样:

Array {
  "com.project.server",
  "com.project.client",
  "com.project.client.util",
  ...
}

未定义一个包可以包含多少层。

现在我想将其转换为分层的 JSON-Object。 这应该是这样的:

{
    "name": "com",
    "children": [
        {
            "name": "project",
            "children": [
                {
                    "name": "server"
                }, 
                {
                    "name": "client",
                    "children": [
                        {
                            "name": "util"
                        }
                    ]
                }
            ]
        }
    ]
}

希望你能明白我的意思

说实话,我被无可救药地质疑了...

你能帮帮我吗? 谢谢,抱歉可能英语不好。

给你!

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

public class ParseTree {

    public PackageInfo getRoot(List<String> packages) throws JsonProcessingException {
        Map<String, PackageInfo> map = new HashMap<>();

        String root = null;
        for (String packageName : packages) {
            String[] split = packageName.split("\.");
            for (int i = 0; i < split.length; i++) {
                String singlePackage = split[i];
                if (root == null) {
                    root = singlePackage;
                }
                map.computeIfAbsent(singlePackage, PackageInfo::new);
                if (i - 1 >= 0) {
                    PackageInfo currentPackage = map.get(singlePackage);
                    map.get(split[i - 1]).getChildren().add(currentPackage);
                }
            }
        }

        return map.get(root);
    }

    public static void main(String[] args) throws JsonProcessingException {
        List<String> packages = Arrays.asList("com.project.server",
            "com.project.client",
            "com.project.client.util", "com.project.client.util.some");

        ParseTree parseTree = new ParseTree();
        PackageInfo root = parseTree.getRoot(packages);
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.writeValueAsString(root));
    }
}

class PackageInfo {

    private String name;
    private Set<PackageInfo> children;

    public PackageInfo(String name) {
        this.name = name;
        children = new HashSet<>();
    }

    public Set<PackageInfo> getChildren() {
        return children;
    }

    public String getName() {
        return name;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        PackageInfo that = (PackageInfo) o;
        return Objects.equals(name, that.name);
    }

    @Override
    public int hashCode() {

        return Objects.hash(name);
    }

    @Override
    public String toString() {
        return "PackageInfo{" +
            "name='" + name + '\'' +
            ", children=" + children +
            '}';
    }
}

它将为您提供

的输出
{
   "name":"com",
   "children":[
      {
         "name":"project",
         "children":[
            {
               "name":"server",
               "children":[

               ]
            },
            {
               "name":"client",
               "children":[
                  {
                     "name":"util",
                     "children":[
                        {
                           "name":"some",
                           "children":[

                           ]
                        }
                     ]
                  }
               ]
            }
         ]
      }
   ]
}

听起来你需要 Java 中的树结构。已经讨论了多种解决方案 here

然后您可以以标准方式转换 input/output JSON。

对于包的具体问题,请考虑使用树状实现。您可以使树只包含唯一节点。这将使您能够将数据转换为正确的格式。 下面是一些关于如何创建你想要的树的伪代码:

class Tree
    Tree[] children
     String data;

现在要向这棵树添加内容,您只需像链表一样遍历它,这意味着您添加了按编号访问子项的方法。此外,当您添加节点时,通过将它们与您正在添加的级别上已经存在的节点进行比较,确保它们是唯一的。由于您更关注从 Tree 到 Json 的实际转换。

一种可能的算法是递归遍历树并从中创建一个 String,如下所示:

public String getJsonFormat(Tree root){
for(Tree child : root.getChildren())
    {
        return "{\n\"name\":\"" + child.data + "\",  \n\"children\":[\n" + getJsonFormat(child) + "\n}"
    }

现在您可以使用 Json。要将内容添加到树中,这里有一个关于如何执行此操作的算法。

addStuffToTree(String packagePath)
    {
     array = packagePath.split("\.");
     //We now know that the elements in the array, correspond to the level of the tree they are supposed to be in, therefore:
    Tree temp = root; //new Tree which is equal to your root
     if(temp.data != array[0])
    for( i=1; i < array.length; i++){
        for(Tree tree : temp.getChildren())
            if(tree.data == array[i])
                 {temp=tree;
                 i++;
                 // We will traverse the tree like this, avoiding duplicates
                  }
         temp.add(array[i])
         temp = newest child
          //This adds a node if it hasn't been there yet if there are more iterations, it will continue running under that node, if not it will exit the loop
    }

抱歉,这不是很漂亮,是在我的 phone 上制作的。

与其他解决方案没有太大区别,但既然我这样做了,就给你

@Data
public class Node {
    String name;
    List<Node> children;
    public Node(String name) {
        this.name = name;
        children = new ArrayList<>();
    }
}

public static void main(String[] args) {
    List<String> a = Arrays.asList(
            "com.project.server",
            "com.project.client",
            "com.project.client.util"
        );
    List<Node> root = new ArrayList<>();
    for (String s: a) {
        List<String> packs = Arrays.asList(s.split("\."));
        List<Node> current = root;
        for (String pack : packs) {
            Optional<Node> newCur = current.stream().filter(node -> node.name.equals(pack)).findFirst();
            if (newCur.isPresent()) {
                current = newCur.get().children;
            } else {
                Node newNode = new Node(pack); 
                current.add(newNode);
                current = newNode.children;
            }
        }
    }
    System.out.println(root);
}

json 转换应该是非常标准的

使用 lomboks 生成的 toString 输出:

[Node(name=com, children=[Node(name=project, children=[Node(name=server, children=[]), Node(name=client, children=[Node(name=util, children=[])])])])]