【问题标题】:Grouping ArrayList into JSON Arrays/Objects将 ArrayList 分组为 JSON 数组/对象
【发布时间】:2018-11-03 20:25:15
【问题描述】:

我在数据库中有一个文件结构,路径和文件名作为列,并希望将它们组合在一起,但不知道该怎么做。这是我目前使用的精简版:

//in this example, list is the returned data
JSONArray jList1 = new JSONArray();
for (int a = 0; a < list.size(); a++){
    Object[] fileObj = (Object[])list.get(a);
    String folder = (String)fileObj[0];
    String filename = (String)fileObj[1];
    JSONObject jObj1 = new JSONObject();
    jObj1.put("path",folder);
    jObj1.put("filename",filename);
    jList1.add(jObj1);
}
response.getWriter().write(jList1.toJSONString());

这会将所有内容放入同一个 JSONArray。以下是输出示例:

[
    {
        path: "/a",
        filename: ""
    },
    {
        path: "/a",
        filename: "file1.png"
    },
    {
        path: "/a/b",
        filename: ""
    },
    {
        path: "/a/b",
        filename: "file2.png"
    },
    {
        path: "/a/b",
        filename: "file3.png"
    },
    {
        path: "/a/c",
        filename: ""
    },
    {
        path: "/a/c",
        filename: "file4.jpg",
    },
    {
        path: "/",
        filename: "file5.jpg",
    },
    {
        path: "/",
        filename: "file6.jpg",
    }
]

我想要这样的:

[
    {
        path: "/a",
        filename: ""
        files: [
            {
                path: "/a/b",
                filename: ""
                files: [
                    {
                        path: "/a/b",
                        filename: "file2.png"
                    },
                    {

                        path: "/a/b",
                        filename: "file3.png"
                    }
                ]
            },          
            {
                path: "/a/c",
                filename: ""
                files: [
                    {
                        path: "/a/c",
                        filename: "file4.jpg",
                    }
                ]
            },
            {
                path: "/a",
                filename: "file1.png"
            }
        ]
    },
    {
        path: "/",
        filename: "file5.jpg",
    },
    {
        path: "/",
        filename: "file6.jpg",
    }
]

现在我可以知道确切的级别数来执行此操作,但不确定如何处理树的未知级别数。我为示例取出的每个对象中还有其他属性,这就是为什么我不只是将文件名本身放入数组中。

我忽略了数据库结构,因为我认为它并不真正需要。唯一的问题可能是它的顺序,我有:

order by (CASE WHEN path='/' THEN 1 ELSE 0 END), path, filename

基本上每个级别都有顶部的文件夹和底部的文件。

有人可以让我按照我正在寻找的方式构建 JSON 吗?我知道与以前的记录相比,它必须是某种存储记录,但似乎无法弄清楚如何构建它。我曾考虑对每个目录进行不同的查询,但这会导致对数据库的大量访问,从而导致性能问题。

【问题讨论】:

  • 你为什么需要像这样嵌套它们,我觉得任何只有文件路径的条目都是多余的,因为该路径中的任何项目都存在该信息,那就是没有意义 @987654325 @当你有"/a/b","file2.png"然后你可以从第二项中提取父路径。
  • 我需要嵌套它们以获得最终输出。模板像这样嵌套它们以进行显示。我理解你所说的没有这样列出的文件夹,但我知道我在那里是因为该文件夹在对象中有更多信息,如修改日期、文件数量等。为简单起见,我将其删除。

标签: java json arraylist multidimensional-array


【解决方案1】:

我最终通过创建一个 ResourceTree 类来做到这一点:

public class ResourceTree {
    private String parentPath;
    private List<ResourceTree> childrenItems;
    private JSONObject jObj1;

    public ResourceTree() {
        this.parentPath = "";
        this.childrenItems = new ArrayList<ResourceTree>();
    }

    public String getParentPath() {
        return parentPath;
    }

    public void setParentPath(String parentPath) {
        this.parentPath = parentPath;
    }

    public JSONObject getResourceObj() {
        return jObj1;
    }

    public void setResourceObj(JSONObject jObj1) {
        this.jObj1 = jObj1;
    }

    public List<ResourceTree> getChildrenItems() {
        return childrenItems;
    }

    public void setChildrenItems(List<ResourceTree> childrenItems) {
        this.childrenItems = childrenItems;
    }

    public void addChildrenItem(ResourceTree childrenItem){
        if(!this.childrenItems.contains(childrenItem))
            this.childrenItems.add(childrenItem);
    }

    public JSONArray getFileList() {
        JSONArray jList1 = new JSONArray();
        JSONObject jObj2 = new JSONObject();
        List rtChilds = getChildrenItems();
        for (int i = 0; i < rtChilds.size(); i++) {
            ResourceTree rt = (ResourceTree)rtChilds.get(i);
            jObj2 = rt.getResourceObj();
            if (rt.getChildrenItems().size() > 0) {
                jObj2.put("files",rt.getFileList());
            }
            jList1.add(jObj2);
        }
        return jList1;
    }
}

从那里,我为每个项目创建一个 ResourceTree 并添加到适用的子项目中。

//list is an ArrayList of objects
if (list != null && list.size() > 0) {
    Map<String, ResourceTree> hm = new LinkedHashMap();
    for (int b = 0; b < list.size(); b++){
        Object[] fileObj = (Object[])list.get(b);
        if (fileObj != null) {
            String folder = (String)fileObj[0];
            String parentFolder = folder;
            String fn = (String)fileObj[1];
            String type = "";
            if (fn.equals("")) {
                parentFolder = folder.substring(0,folder.lastIndexOf("/"));
            }
            jObj1 = new JSONObject();
            jObj1.put("path",folder);
            jObj1.put("filename",fn);   

            ResourceTree rt = new ResourceTree();
            rt.setResourceObj(jObj1);
            rt.setParentPath(parentFolder);
            if (fn.equals("")) {
                hm.put(folder,rt);
            }
            ResourceTree rtParent;
            if (hm.containsKey(parentFolder)){
                rtParent = hm.get(parentFolder);
            } else {
                rtParent = new ResourceTree();
                rtParent.setParentPath(parentFolder.substring(0,parentFolder.lastIndexOf("/")));
                hm.put(parentFolder,rtParent);
            }
            rtParent.addChildrenItem(rt);
        }
    }
    List<ResourceTree> DX = new ArrayList<ResourceTree>();
        for (ResourceTree rt : hm.values()) {
            //path is the top level folder specified
            if (rt.getParentPath().equals(path.substring(0,path.lastIndexOf("/")))) {
                jList1.addAll(rt.getFileList());
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    我有一个建议可以尝试解决您的问题。

    首先创建一个文件来存储每个文件/目录的值。示例如下:

    import java.util.ArrayList;
    import java.util.List;
    
    public class Archive implements Comparable<Archive> {
    
        private String path;
        private String filename;
        List<Archive> files;
    
        public Archive(String path, String filename) {
            this.path = path;
            this.filename = filename;
            this.files = new ArrayList<Archive>();
        }
    
        public String getPath() {
            return path;
        }
    
        public String getFilename() {
            return filename;
        }
    
        public List<Archive> getFiles() {
            return files;
        }
    
        @Override
        public String toString() {
            return "Path = "+ path + ", Filename = "+ filename;
        }
    
        @Override
        public int compareTo(Archive archive) {
            return getPath().compareTo(archive.getPath());
        }
    
    }
    

    现在让我们创建将读取您的文件夹并创建存档类列表的方法:

    public static void listFilesFromFolder(final File folder, final List<Archive> listArchive) {
        for (File file : folder.listFiles()) {
            if (file.isFile()) {
                String path = file.getPath().replace(mainFolderPath, "").replace(file.getName(), "");
                Archive archive = new Archive(path, file.getName());
                listArchive.add(archive);
            }
        }
    
        for (File file : folder.listFiles()) {
            if (file.isDirectory()) {
                String path = file.getPath().replace(mainFolderPath, "");
                Archive archive = new Archive(path, "");
                listArchive.add(archive);
                listFilesFromFolder(file, archive.getFiles());
            }
        }
    }
    

    接下来我们将创建将 List 转换为 JSON 的方法。

    public static String listToJSON(List<Archive> listArchive) {
        ObjectMapper mapper = new ObjectMapper();
        try {
            return mapper.writeValueAsString(listArchive);
        } catch (JsonGenerationException e) {
            e.printStackTrace();
        } catch (JsonMappingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    
        return "";
    }
    

    最后我们将创建 Main 方法来运行我们的应用程序:

    public class Test {
    
        final static String mainFolderPath = "c:\\MyFolder";
    
        public static void main(String[] args) {
            File folder = new File(mainFolderPath);
    
            List<Archive> listArchive = new ArrayList<Archive>();
    
            listFilesFromFolder(folder, listArchive);
    
            Collections.sort(listArchive);
    
            System.out.println( listToJSON(listArchive) );
        }
    }
    

    仅供参考,请遵循所使用的导入:

    import java.io.File;
    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    import org.codehaus.jackson.JsonGenerationException;
    import org.codehaus.jackson.map.JsonMappingException;
    import org.codehaus.jackson.map.ObjectMapper;
    

    我希望我有所帮助。

    【讨论】:

    • 抱歉没有回复。我还没来得及复习这件事就走了。感谢您抽出宝贵的时间。这种结构需要遍历每个文件夹中的文件,在我的情况下这将是多个查询。
    猜你喜欢
    • 1970-01-01
    • 2018-11-13
    • 2011-02-14
    • 1970-01-01
    • 1970-01-01
    • 2019-12-06
    • 2020-05-02
    • 1970-01-01
    • 2016-09-19
    相关资源
    最近更新 更多