Java-动态访问嵌套的JSONArray值

时间:2019-03-13 21:49:08

标签: java json

我有一个JSON文件(myjsonfile.json),其中将文件夹结构以及文件内容存储为JSON。如下:

{
  "name":"folder1",
  "type":"directory",

  "children":[
    {"name":"info",
      "type":"directory",
      "children": [
        {
        "name":"info1.txt",
        "type":"file",
        "content": ["abcd", "efgh", "ijk"]
        }]
    },
    {"name":"data",
     "type":"directory",
     "children": [{
          "name":"data1.txt",
          "type":"file",
          "content": ["abcd", "xyz"]
        }]
    }
  ]
}

我想做的是动态访问两个文本文件(contentinfo1.txt)中的一个的data1.txt并将其存储为字符串列表。动态是指用户提供文件名,即密钥(info1.txtdata1.txt)。

我可以像这样使用org.json库以静态方式解析和获取值:

         File file = new File(myfilepath/myjsonfile.json);
         String jsonContent = null;
         try {
             content = FileUtils.readFileToString(file, "utf-8");
         } catch (IOException e) {
             e.printStackTrace();
         }

         // Convert JSON string to JSONObject
         JSONObject jsonObj = new JSONObject(jsonContent);
         JSONArray children =  jsonObj.getJSONArray("children");
         System.out.println(children.toString());
         JSONObject  child0 = children.getJSONObject(0);
         System.out.println(child0.toString());
         // and so on...

但是,我无法弄清楚如何使它动态化,并根据文件名的用户输入将文件内容存储为字符串列表。

有人可以帮我吗?

编辑:澄清了问题。 myfilepath是指JSON文件(myjsonfile.json)的文件路径。

2 个答案:

答案 0 :(得分:1)

您需要遍历每个对象,并查看name是否具有您要查找的文件。我建议您使用更详细的JSON处理库(例如Jackson或Gson)使事情变得更容易。但是,考虑到当前的实现方式,您需要按照以下方式进行操作:

        if(jsonObj.has("children")) {
            JSONArray mainChild = jsonObj.getJSONArray("children");
            for(int i=0; i < mainChild.length(); i++) {
                if(((JSONObject)mainChild.get(i)).has("children")) {
                    JSONArray child = ((JSONObject)mainChild.get(i)).getJSONArray("children");
                    for(int j=0; j < child.length(); j++) {
                        JSONObject obj = child.getJSONObject(j);
                        if(obj.has("name") 
                                && fileNameToLookFor.equals(obj.getString("name"))) {
                            if(obj.has("content")) {
                                return obj.getJSONArray("content");
                            }
                            return null;
                        }
                    }
                }
            }
            return null;
        }

答案 1 :(得分:0)

实施自己的tree-node-walker

class NodeWalker {

    private final JSONObject object;

    public NodeWalker(JSONObject object) {
        this.object = object;
    }

    public List<String> findContentFor(String name) {
        LinkedList<JSONObject> queue = new LinkedList<>();
        queue.add(object);
        while (queue.size() > 0) {
            JSONObject next = queue.pop();
            Object fileName = next.get("name");
            final String contentName = "content";
            if (fileName != null && fileName.equals(name) && next.has(contentName)) {
                JSONArray content = next.getJSONArray(contentName);
                if (content == null) {
                    return Collections.emptyList();
                }
                List<String> result = new ArrayList<>();
                IntStream.range(0, content.length()).forEach(i -> result.add(content.getString(i)));
                return result;
            }
            final String childrenName = "children";
            if (next.has(childrenName)) {
                JSONArray array = next.getJSONArray(childrenName);
                IntStream.range(0, array.length()).forEach(i -> queue.add(array.getJSONObject(i)));
            }
        }

        return Collections.emptyList();
    }
}

简单用法:

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.File;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.IntStream;

public class ProfileApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();
        List<String> strings = Files.readAllLines(jsonFile.toPath());
        String json = String.join("", strings);

        JSONObject jsonObj = new JSONObject(json);

        NodeWalker nodeWalker = new NodeWalker(jsonObj);
        String[] files = {"info1.txt", "data1.txt", "data2.txt"};
        for (String file : files) {
            System.out.println(file + " contents -> " + nodeWalker.findContentFor(file));
        }
    }
}

打印:

info1.txt contents -> [abcd, efgh, ijk]
data1.txt contents -> [abcd, xyz]
data2.txt contents -> []

Gson

更容易使用JSON有效负载的Gson库和类模型。让我们创建一个类:

class FileNode {

    private String name;
    private String type;
    private List<FileNode> children;
    private List<String> content;

    public List<String> findContent(String name) {
        LinkedList<FileNode> queue = new LinkedList<>();
        queue.add(this);
        while (queue.size() > 0) {
            FileNode next = queue.pop();
            if (next.name.equals(name)) {
                return next.content;
            }
            if (next.children != null) {
                queue.addAll(next.children);
            }
        }

        return Collections.emptyList();
    }

    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 List<FileNode> getChildren() {
        return children;
    }

    public void setChildren(List<FileNode> children) {
        this.children = children;
    }

    public List<String> getContent() {
        return content;
    }

    public void setContent(List<String> content) {
        this.content = content;
    }

    @Override
    public String toString() {
        return "FileNode{" +
                "name='" + name + '\'' +
                ", type='" + type + '\'' +
                ", children=" + children +
                ", content=" + content +
                '}';
    }
}

我们可以如下使用:

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.io.File;
import java.io.FileReader;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

public class GsonApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();

        Gson gson = new GsonBuilder()
                .setPrettyPrinting()
                .create();

        FileNode root = gson.fromJson(new FileReader(jsonFile), FileNode.class);
        String[] files = {"info1.txt", "data1.txt", "data2.txt"};
        for (String file : files) {
            System.out.println(file + " contents -> " + root.findContent(file));
        }
    }
}

上面的代码显示:

info1.txt contents -> [abcd, efgh, ijk]
data1.txt contents -> [abcd, xyz]
data2.txt contents -> []