使用 JSONPath 遍历大型 JSON 数组

Iterate over a large JSON Array with JSONPath

我有一个简单的 Java 应用程序,它需要遍历一个大型 JSON 数组(包含大约 20K 项),并且在每个数组中,我解析一个子数组。每一项看起来像这样:

{"index":0,"f1":[2,16,16,16,16,16,32,16],"f2":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],"startTime":0.0}

我正在使用 JSONPath 遍历每个项目。我所做的是首先读取长度,然后简单地遍历整个数组。但速度很慢(例如,每秒 1 个项目)。

int length = JsonPath.read(response, "$.result.length()");
for (int i = 0; i < length; i++) {
    double start_time = JsonPath.read(response, "$.result["+i+"].startTime");
    ArrayList<Integer> f1= JsonPath.read(response, "$.result["+i+"].f1");
    //...other things
}

有什么办法可以优化吗?

知道了。感谢 Erwin,我可以像这样将整个 JSON 立即解析为 HASHMap

ArrayList<HashMap> json= JsonPath.read(response, "$.result");

然后我们可以简单地调用get(i)来访问循环中的特定项目:

double start_time = (double) json.get(i).get("startTime");

您应该尽量减少 read 操作的数量。第一次扫描整个文件,然后部分扫描 n 次文件。从磁盘读取比从内存读取慢:Latency Numbers Every Programmer Should Know, so you should load the file to memory once and then iterate over items. Also, from JsonPath 文档:

If you only want to read once this is OK. In case you need to read an other path as well this is not the way to go since the document will be parsed every time you call JsonPath.read(...). To avoid the problem you can parse the json first.

String json = "...";
Object document = Configuration.defaultConfiguration().jsonProvider().parse(json);

List<Integer> f10 = JsonPath.read(document, "$.result[0].f1");
List<Integer> f11 = JsonPath.read(document, "$.result[1].f1");

您可以通过以下方式改进您的 JsonPath$.result 并只阅读您需要的内容:$.result..['f1','startTime']

仅加载必填字段的示例应用程序:

import com.jayway.jsonpath.JsonPath;

import java.io.File;
import java.util.List;
import java.util.Map;

public class JsonPathApp {

    public static void main(String[] args) throws Exception {
        File jsonFile = new File("./resource/test.json").getAbsoluteFile();
        List<Object> array = JsonPath.read(jsonFile, "$.result..['f1','startTime']");
        for (Object item : array) {
            Map<String, Object> map = (Map<String, Object>) item;
            System.out.println(map.get("f1"));
            System.out.println(map.get("startTime"));
        }
    }
}