java 使用列表/表中的 json 创建树

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10660167/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 01:59:38  来源:igfitidea点击:

Creating a tree using json from a list/table

javajsontree

提问by Bob Stein

Let's say I have table/list like this n=3 in this case, but n can be as unlimited.

假设在这种情况下我有这样的表/列表 n=3,但 n 可以是无限的。

groupid       answerid1     answerid2     answerid(n)
1              3            6             8 
1              3            6             9 
1              4            7               
2              5                            

and i want to create a parent/child tree json output like this using java.(I have been using GSON)

我想使用java创建一个这样的父/子树json输出。(我一直在使用GSON)

    {
        data: [
            {
                groupid: 1,
                children: [
                    {
                        answerid1: 1,
                        children: [
                            {
                                answerid2:3,
                                children: [
                                           {
                                    answerid3:6,
                                                  children: [
                                                              {answerid4: 8},
                                  {answerid4: 9} 
                                                             ]
                                              } 


                            }, {
                                 answerid2: 4,
                                 children: [
                                          {answerid3:7} 
                                   ]
                                 }
                                ]         
                    }, 

               {
                 groupid1: 2,
                 children: [
                       { answerid2: 5}
                        ]
                }

               ]      
        }

what would be the code/steps to do so. i have looked through lots of tags but mostly people are printing the output and not recursively build a hashmap/ArrayList for GSON to parse adn write to API. one other point each id has other data associated with it that will have to be included in the json output. for instance instead of {groupid:1} would need to this {groupid:1, text=toyota}.

这样做的代码/步骤是什么。我查看了很多标签,但大多数人都在打印输出,而不是递归地为 GSON 构建哈希图/ArrayList 来解析和写入 API。另一个点是每个 id 都有其他与之关联的数据,这些数据必须包含在 json 输出中。例如,而不是 {groupid:1} 需要这个 {groupid:1, text=toyota}。

any help is greatly appreciated as i am fairly new to java as i come from SAS background.

非常感谢任何帮助,因为我对 Java 还很陌生,因为我来自 SAS 背景。

I get data like this (just a matrix of list) Toyota, Gas, Compact, Corolla

我得到这样的数据(只是一个列表矩阵)Toyota、Gas、Compact、Corolla

  • Toyota, Gas, Compact, Camry
  • 丰田,汽油,紧凑型,凯美瑞
  • Toyota, Hybrid, Compact, Prius
  • 丰田、混合动力、紧凑型、普锐斯
  • Honda, Gas, Compact, Civic
  • 本田,汽油,紧凑型,思域
  • If needed I can REFORMAT THE DATA into two tables

    parentId parText answerId

  • 如果需要,我可以将数据重新格式化为两个表

    parentId parText answerId

  • 1 Toyota 1
  • 1 丰田 1
  • 1 Toyota 2
  • 1 丰田 2
  • 1 Toyota 3
  • 1 丰田 3
  • 2 Honda 4
  • 2 本田 4
  • answerId level answerTextid answerText

  • answerId 级别 answerTextid answerText

  • 1 1 1 Gas
  • 1 1 1 气体
  • 1 2 2 Compact
  • 1 2 2 紧凑型
  • 1 3 3 Corolla
  • 1 3 3 卡罗拉
  • 2 1 1 Gas
  • 2 1 1 气体
  • 2 2 2 Compact
  • 2 2 2 紧凑型
  • 2 3 4 Camry
  • 2 3 4 凯美瑞
  • Then I need to make it a tree(nested output like the JSON shows with parent/children - just like if you were creatign a file system directory)

    one other thign i would like to do is for each car have mileage as a varialbe ({answerid3:4, text=Corolla, mileage=38}. but also if i traverse up the tree give an average mile for the branch. Like say at branch Toyota, Gas, Compact the mileage would be avg(Camry, Corolla)

    the output is a little off, i am looking for something like this. if no children then no children arraylist, and attrbutes are part of one object (hashmap)

    {"data":[{"id":1,"children":
        [{"id": 2,"children":
            [{"id": 3 ,"children":
                [{"id": 4,"name":"Prius"}],"name":"Compact"}],"name":"Hybrid"},
        {"id":5,"children":
            [{"id":3,"children":
                [{"id":7,"MPG":38, "name":"Corolla"},
                 {"id":8,"MPG":28,"name":"Camry"}],"name":"Compact"}],"name":"Gas"}],"name":"Toyota"},
    {"id":9, "children":
        [{"id":10,"children":
            [{"id":3 ,"children":
                [{"id":11 ,"name":"Civic"}],"name":"Compact"}],"name":"Gas"}],"name":"Honda"}]}
    
  • 然后我需要把它变成一棵树(嵌套输出就像 JSON 显示的父/子 - 就像你创建一个文件系统目录一样)

    我想做的另一件事是,每辆车都有里程作为变量({answerid3:4, text=Corolla, mileage=38}。但如果我遍历树,则为分支提供平均英里。就像说在分公司 Toyota、Gas、Compact 的行驶里程为平均(凯美瑞、卡罗拉)

    输出有点偏离,我正在寻找这样的东西。如果没有孩子,则没有孩子数组列表,并且属性是一个对象(哈希图)的一部分

    {"data":[{"id":1,"children":
        [{"id": 2,"children":
            [{"id": 3 ,"children":
                [{"id": 4,"name":"Prius"}],"name":"Compact"}],"name":"Hybrid"},
        {"id":5,"children":
            [{"id":3,"children":
                [{"id":7,"MPG":38, "name":"Corolla"},
                 {"id":8,"MPG":28,"name":"Camry"}],"name":"Compact"}],"name":"Gas"}],"name":"Toyota"},
    {"id":9, "children":
        [{"id":10,"children":
            [{"id":3 ,"children":
                [{"id":11 ,"name":"Civic"}],"name":"Compact"}],"name":"Gas"}],"name":"Honda"}]}
    
  • 采纳答案by Malcolm Smith

    You should create classes to model your data, in the structure you require. You are basically wanting to build a hierarchical structure from some row based data, this is quite like an XML document, which might be an appropriate solution. But you got me hooked so I played about with what I had before and came up with this:

    您应该按照您需要的结构创建类来为您的数据建模。您基本上想从一些基于行的数据构建一个层次结构,这很像一个 XML 文档,这可能是一个合适的解决方案。但是你让我着迷了,所以我玩弄了我以前拥有的东西并想出了这个:

    public class Test { 
    
        public static void main(String[] args) 
        {
            // hierarchical data in a flattened list
            String[][] data = {
                    {"Toyota", "Gas", "Compact", "Corolla"},
                    {"Toyota", "Gas", "Compact", "Camry"},
                    {"Toyota", "Hybrid", "Compact", "Prius"},
                    {"Honda", "Gas", "Compact", "Civic"}
            };
    
            TreeManager treeManager = new TreeManager();
    
            for(String[] row : data)
            {
                // build the path to our items in the tree
                List<String> path = new ArrayList<String>();
                for(String item : row)
                {
                    // add this item to our path
                    path.add(item);
                    // will add it unless an Item with this name already exists at this path
                    treeManager.addData(treeManager, path);
                }
            }
    
            treeManager.getData(data[0]).putValue("MPG", 38);
            treeManager.getData(data[1]).putValue("MPG", 28);
    
            Gson gson = new Gson();
    
            System.out.println(gson.toJson(treeManager));
        }
    
        /**
         * This base class provides the hierarchical property of
         * an object that contains a Map of child objects of the same type.
         * It also has a field - Name
         *
         */
        public static abstract class TreeItem implements Iterable<TreeItem>{
    
            private Map<String, TreeItem> children;     
            private String name;
    
            public TreeItem() {
                children = new HashMap<String, TreeItem>();
            }
    
            public String getName() {
                return name;
            }
    
            public void setName(String name) {
                this.name = name;
            }
    
            public void addChild(String key, TreeItem data) 
            {           
                children.put(key, data);
            }
    
            public TreeItem getChild(String key) 
            {           
                return children.get(key);
            }
    
            public boolean hasChild(String key) 
            {           
                return children.containsKey(key);
            }
    
            @Override
            public Iterator<TreeItem> iterator() {          
                return children.values().iterator();
            }           
        }
    
        /**
         * This is our special case, root node. It is a TreeItem in itself
         * but contains methods for building and retrieving items from our tree
         *
         */
        public static class TreeManager extends TreeItem
        {       
            /**
             * Will add an Item to the tree at the specified path with the value
             * equal to the last item in the path, unless that Item already exists 
             */
            public void addData(List<String> path)
            {
                addData(this, path);
            }
    
            private void addData(TreeItem parent, List<String> path)
            {
                // if we're at the end of the path - create a node
                String data = path.get(0);
                if(path.size() == 1)
                {
                    // unless there is already a node with this name
                    if(!parent.hasChild(data))
                    {
                        Group group = new Group();
                        group.setName(data);
                        parent.addChild(data, group);
                    }
                }
                else
                {
                    // pass the tail of this path down to the next level in the hierarchy
                    addData(parent.getChild(data), path.subList(1, path.size()));
                }
            }
    
            public Group getData(String[] path)
            {
                return (Group) getData(this, Arrays.asList(path));
            }
    
            public Group getData(List<String> path)
            {
                return (Group) getData(this, path);
            }
    
            private TreeItem getData(TreeItem parent, List<String> path)
            {
                if(parent == null || path.size() == 0)
                {
                    throw new IllegalArgumentException("Invalid path specified in getData, remainder: " 
                            + Arrays.toString(path.toArray()));
                }
                String data = path.get(0);
                if(path.size() == 1)
                {
                    return parent.getChild(data);
                }
                else
                {
                    // pass the tail of this path down to the next level in the hierarchy
                    return getData(parent.getChild(data), path.subList(1, path.size()));
                }
            }
        }
    
        public static class Group extends TreeItem {
    
            private Map<String, Object> properties;
    
            public Object getValue(Object key) {
                return properties.get(key);
            }
    
            public Object putValue(String key, Object value) {
                return properties.put(key, value);
            }
    
            public Group () {
                super();
                properties = new HashMap<String, Object>();
            }       
        }
    }
    

    I think this meets most of the requirements you've mentioned so far, although I left out the averaging of the MPG values as an exercise for the reader (I've only got so much time...). This solution is very generic - you may want more concrete sub-classes that better describe your data model (like Manufacturer, Type, Model), as you will then be able to hang more useful methods off them (like calculating averages of fields in child objects) , and you wouldn't have to deal with the properties as a collection of Objects, but you then get more complicated code initialising your data structure from the list. Note - this is not production ready code, I've just provided it as an example of how you might go about modelling your data in Java.

    我认为这符合您目前提到的大部分要求,尽管我省略了 MPG 值的平均值作为读者练习(我只有这么多时间......)。此解决方案非常通用 - 您可能需要更具体的子类来更好地描述您的数据模型(如制造商、类型、模型),因为您将能够从它们中悬挂更多有用的方法(如计算子类中字段的平均值) objects) ,并且您不必将属性作为Objects的集合来处理,但是您会得到更复杂的代码来初始化列表中的数据结构。注意 - 这不是生产就绪代码,我只是提供它作为您如何在 Java 中建模数据的示例。

    If you are new to not only Java but Object Orientated Programmingthen you should read up on the subject. The code I have written here is not perfect, I can already see ways it could be improved. Learning to write good quality object orientated code takes time and practice. Read up on Design Patternsand Code Smells.

    如果您不仅不熟悉 Java,而且不熟悉面向对象编程,那么您应该阅读该主题。我在这里编写的代码并不完美,我已经可以看到可以改进的方法。学习编写高质量的面向对象代码需要时间和练习。阅读设计模式代码气味