使用JSONPath遍历大型JSON数组

时间:2019-03-26 21:32:28

标签: java arrays json parsing jsonpath

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

{"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
}

有没有一种优化方法?

2 个答案:

答案 0 :(得分:1)

您应该减少read操作的次数。第一次扫描整个文件,然后再次扫描n次,部分文件。从磁盘读取的速度比从内存读取的速度慢:Latency Numbers Every Programmer Should Know,因此应将文件加载到内存一次,然后遍历所有项目。另外,来自JsonPath文档:

  

如果您只想阅读一次,则可以。如果您需要阅读   其他路径也不可行,因为文档将   每次调用JsonPath.read(...)时都会被解析。为了避免这个问题   您可以先解析json。

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

答案 1 :(得分:0)

知道了。感谢Erwin,我可以将整个JSON一次解析成HASHMap,就像这样:

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

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

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