【问题标题】:Convert an array to hierarchical JSONArray将数组转换为分层 JSONArray
【发布时间】:2018-08-20 14:38:48
【问题描述】:

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

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

它没有定义一个包可以包含多少级别。

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

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

我希望你能明白我想要什么。

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

你能帮帮我吗? 感谢并为可能的英语不好感到抱歉。

【问题讨论】:

    标签: java arrays json hierarchical


    【解决方案1】:

    你去!

    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 1.8,所以我必须用“map.computeIfAbsent(singlePackage, PackageInfo::new)”更改部分。对 1.7 有什么想法吗?
    • if (!map.contains(singlePackage)) { map.put(singlePackage, new PackageInfo(singlePackage)) }
    【解决方案2】:

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

    然后您可以以标准方式转换输入/输出 JSON。

    【讨论】:

      【解决方案3】:

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

      class Tree
          Tree[] children
           String data;
      

      现在要向这棵树添加东西,您只需像链表一样遍历它,这意味着您添加方法来按数字访问子级。此外,当您添加节点时,请确保它们是唯一的,通过将它们与您添加它的级别上已经存在的节点进行比较。由于您更关注从树到 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
          }
      

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

      【讨论】:

      • 非常感谢您的努力,我会尽量使用您的想法。
      【解决方案4】:

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

      @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=[])])])])]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-01-31
        • 1970-01-01
        • 2013-03-30
        • 2013-05-08
        • 1970-01-01
        • 1970-01-01
        • 2014-01-30
        相关资源
        最近更新 更多