Группировка ArrayList в массивы / объекты JSON - PullRequest
0 голосов
/ 24 мая 2018

У меня есть файловая структура в базе данных, с путем и именем файла в виде столбцов, и я хочу сгруппировать их вместе, но не знаю, как это сделать.Вот урезанная версия того, что я сейчас использую:

//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 так, как я ищу?Я знаю, что это должно быть чем-то вроде хранения записей по сравнению с предыдущими, но просто не могу понять, как его структурировать.Я думал о том, чтобы иметь разные запросы для каждого каталога, но это вызовет много обращений к базе данных, что приведет к проблемам с производительностью.

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

В итоге я сделал это, создав класс 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());
            }
        }
    }
}
0 голосов
/ 24 мая 2018

У меня есть предложение, чтобы попытаться решить вашу проблему.

Сначала создайте файл для хранения значений каждого файла / каталога.Вот пример:

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());
    }

}

Теперь давайте создадим метод, который будет читать вашу папку и создать список классов Archive:

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;

Надеюсь, я помог.

...