0

I have a file system structure parsed as JSON:

{
    "name": "rootf",
    "type": "system",
    "path": "Parsing/rootf",
    "children": [{
        "name": "f1",
        "type": "folder",
        "path": "Parsing/rootf/f1",
        "children": [{
            "name": "subf1",
            "type": "folder",
            "path": "Parsing/rootf/f1/subf1",
            "children": [{
                "name": "text1.txt",
                "type": "file",
                "path": "Parsing/rootf/folder1/subf1/text1.txt",
                "children": ["a", "b", "c"]
            }]
        }, {
            "name": "subf2",
            "type": "folder",
            "path": "Parsing/rootf/f1/subf2",
            "children": []
        }, {
            "name": "text2.txt",
            "type": "file",
            "path": "TParsing/rootf/f1/text2.txt",
            "children": ["d", "e", "f"]
        }]
    }, {
        "name": "text1.txt",
        "type": "file",
        "path": "Parsing/rootd/text1.txt",
        "children": ["aa", "bb"]
    }],
    "_id": "5ce47292d866fc2f40037a56"
}

As can be seen children of type system (denoting the root folder) and of type folder (denoting sub-folders of the root folder) can contain other folders and/or a file. The children of type file contains contents of the file.

I would later need to access individual objects of type folder and type file. What would be the most efficient way to map this to Java objects and how can I access them individually?

I initially tried to use GSON to map it to three classes, System.java, Folder.java and File.java with them containing private List<Folder> children, private List<File> children and private List<String> children respectively. This only works when I have a particular JSON structure (RootFolder->Sub-Folder->File). Is there any way I can make the mapping more generalized so that it includes the condition that a System can contain Folder and File and similarly, a Folder can contain a Folder and File?

Nosrep
  • 521
  • 7
  • 21
  • Why can't you have a `System` class with `List` and a child can be a folder or file as it has a type parameter? If you really want to polymorphism, then you can refer to these links https://stackoverflow.com/questions/30362446/deserialize-json-with-jackson-into-polymorphic-types-a-complete-example-is-giv https://stackoverflow.com/questions/5800433/polymorphism-with-gson https://stackoverflow.com/questions/15736654/how-to-handle-deserializing-with-polymorphism – Abhijith Nagarajan May 21 '19 at 23:06
  • @AbhijithNagarajan, could you please tell me how I could access individual `file` and `folder` objects from that? Actually, for a `System` I need to build a Set of `components` objects. This `components` Set should contain the files and folders objects inside the `System`. I am a bit confused as to how I can do this. –  May 21 '19 at 23:13
  • Can you create a Tree structure from this ? – Amit Kumar Lal May 21 '19 at 23:15
  • @Hades, sorry I don't understand. From what am I supposed to create a Tree structure and why would I need it? Could you please clarify? –  May 21 '19 at 23:19
  • a tree will contain the root folder as its node and further child as its subnode, https://stackoverflow.com/questions/19330731/tree-implementation-in-java-root-parents-and-children. – Amit Kumar Lal May 21 '19 at 23:22

2 Answers2

0

Your original idea seemed fine if you just expand the Folder object to have both private List<Folder> subfolders and private List<File> files, and make the System object a special Folder object. This would allow you to represent your data's layout and anything similar. The only restriction is that only Folders can contain Files and other Folders as children, and Files can contain only Strings as children.

CryptoFool
  • 21,719
  • 5
  • 26
  • 44
  • The restriction is alright as Folder objects will contain only Files and other Folders and I need the contents of the Files as Strings. "make the System object a special Folder object." - What does this mean? Also, I need access to individual objects because my `System.java` extends an abstract class and I have a method which returns a Set of `components` (all nested files and folders) for the `system`. Similarly the `Folder.java` and `File.java` extends an abstract class and I have a method there which returns which `system` a particular `component` belongs to. –  May 21 '19 at 23:52
  • Another question is how will GSON map the files to `private List files` and subfolders to `private List subfolders` because in the JSON it is within the `children` array? Could you provide a concrete example as to how I can do this? –  May 21 '19 at 23:55
0

There was one catch in the JSON that the content was represented as children if its file or folder, hence I have tried a approach where I have replaced the children JSON key with file if it has collection of string with out any JSON object in it using regex. Once its done I just needed one class i.e. Folder in my case to parse this to JSON to a java class.
so My class is as below.

class Folder{  //Can be either system or folder
    private String name;
    private String type;
    private String path;
    private List<Folder> children; //To contain subFolder
    private List<String> file; //To contain list of files
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getPath() {
        return path;
    }
    public void setPath(String path) {
        this.path = path;
    }
    public List<Folder> getChildren() {
        return children;
    }
    public void setChildren(List<Folder> children) {
        this.children = children;
    }
    public List<String> getFile() {
        return file;
    }
    public void setFile(List<String> file) {
        this.file = file;
    }
    @Override
    public String toString() {
        return "Folder [name=" + name + ", type=" + type + ", path=" + path + "\n, children=" + children + ", file="
                + file + "]";
    }
}

Code to convert the key and then parse it to such class

public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        String contents = new String(Files.readAllBytes(Paths.get("C:\\Users\\Sample.json"))); //Java 7 to read JSON into String from file

        Pattern pattern = Pattern.compile("\"children\":\\s*\\[\\s*[\"a-zA-Z\",\\s*]*]",Pattern.MULTILINE); //Pattren to find list of file i.e. content
        Matcher matcher = pattern.matcher(contents);
        while(matcher.find()) {
            String group = matcher.group();
            String newGroup = matcher.group().replaceAll("\"children\"", "\"file\"");
            contents = contents.replace(group, newGroup);
        }
        Folder folder = objectMapper.readValue(contents, Folder.class);
        System.out.println(folder);

    }

output

Folder [name=rootf, type=system, path=Parsing/rootf
, children=[Folder [name=f1, type=folder, path=Parsing/rootf/f1
, children=[Folder [name=subf1, type=folder, path=Parsing/rootf/f1/subf1
, children=[Folder [name=text1.txt, type=file, path=Parsing/rootf/folder1/subf1/text1.txt
, children=null, file=[a, b, c]]], file=null], Folder [name=subf2, type=folder, path=Parsing/rootf/f1/subf2
, children=null, file=[]], Folder [name=text2.txt, type=file, path=TParsing/rootf/f1/text2.txt
, children=null, file=[d, e, f]]], file=null], Folder [name=text1.txt, type=file, path=Parsing/rootd/text1.txt
, children=null, file=[aa, bb]]], file=null]

now you have a hierarchy i.e System at root with folders and file inside it.

Amit Kumar Lal
  • 5,537
  • 3
  • 19
  • 37