1

我试图在每次运行时JSON使用 where 解析一个巨大的数组Gson stream,我只需要一次处理 10 个对象。

所以在第一次运行时,它处理 10。在第二次运行中,它从 11 开始。第三,从 21 日开始,以此类推……你得到了练习。

JSON 数组的格式为:

[
  { "key1": "value1"},
  { "key2": "value2"},
  { "key3": "value3"},
  { "key4": "value4"},
  ..........
  .........
  ..........
  { "key10": "value10"},
  ..........
  .........
  ..........
  { "key20": "value20"},
  ..........
  .........
  ..........
 ]

我正在尝试下面的代码,但似乎它不能正常工作,并且总是从一开始就解析。这就是正在做的事情:

public static void readJsonStream(int skipRows) {
    JsonReader reader = null;
    String FILENAME = "/examples/uh_data.json";
    final InputStream stream = UHReportParser.class.getClass().getResourceAsStream(FILENAME);
    try {
        reader = new JsonReader(new InputStreamReader(stream, "UTF-8"));
        Gson gson = new GsonBuilder().create();

        // Read file in stream mode
        reader.beginArray();
        int count = 1;
        while (reader.hasNext()) {



            if (count++<=skipRows){
                continue;
            } else if(count>skipRows+10){
                break;
            }

            else{

                UserData data = null;

                // Read data into object model
                data = gson.fromJson(reader, UserData.class);  //starts from one again
                String description = data.getDescription();

                }

        }
    } catch (UnsupportedEncodingException ex) {
        ex.printStackTrace();
    } catch (IOException ex) {
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }
}

这里应该修改什么?我怎样才能达到预期的效果?

4

1 回答 1

1

我没有深入分析您的算法,但它似乎没有在“跳过”阶段跳过值,我肯定会重构您的 JSON 流阅读器以使其尽可能干净(至少在我能做到的范围内)做)。这也将允许您尽可能多地重用这种方法。考虑以下方法:

static void readArrayBySkipAndLimitFromBegin(final JsonReader jsonReader, final int skip, final int limit,
        final Consumer<? super JsonReader> callback)
        throws IOException {
    readArrayBySkipAndLimit(jsonReader, skip, limit, true, false, callback);
}

static void readArrayBySkipAndLimit(final JsonReader jsonReader, final int skip, final int limit, final boolean processBegin,
        final boolean processEnd, final Consumer<? super JsonReader> callback)
        throws IOException {
    // the JSON stream can be already processed somehow
    if ( processBegin ) {
        jsonReader.beginArray();
    }
    // just skip the `skip`
    for ( int i = 0; i < skip && jsonReader.hasNext(); i++ ) {
        jsonReader.skipValue();
    }
    // and limit to the `limit` just passing the JsonReader instance to its consumer elsewhere
    for ( int i = 0; i < limit && jsonReader.hasNext(); i++ ) {
        callback.accept(jsonReader);
    }
    // in case you need it ever...
    if ( processEnd ) {
        while ( jsonReader.hasNext() ) {
            jsonReader.skipValue();
        }
        jsonReader.endArray();
    }
}

这是我用来测试它的 JSON 文档(总共 32 个数组元素):

[
    {"key1": "value1"},
    {"key2": "value2"},
    ...
    {"key31": "value31"},
    {"key32": "value32"}
]

现在,测试它:

private static final Gson gson = new Gson();
private static final Type mapOfStringToStringType = new TypeToken<Map<String, String>>() {}.getType();

public static void main(final String... args)
        throws IOException {
    // read up to 2B+ entries, every 10 rows
    for ( int i = 0; i >= 0; i += 10 ) {
        System.out.print("Step #" + i / 10 + ": ");
        final Collection<Map<String, String>> maps = new ArrayList<>();
        // consume and close
        try ( final JsonReader jsonReader = Resources.getPackageResourceJsonReader(Q50737654.class, "array.json") ) {
            // consume the JSON reader, parse each array page element and add it to the result collection
            readArrayBySkipAndLimitFromBegin(jsonReader, i, 10, jr -> maps.add(gson.fromJson(jr, mapOfStringToStringType)));
        }
        System.out.println(maps);
        if ( maps.isEmpty() ) {
            break;
        }
    }
    System.out.println("Done");
}

示例输出:

Step #0: [{key1=value1}, {key2=value2}, {key3=value3}, {key4=value4}, {key5=value5}, {key6=value6}, {key7=value7}, {key8=value8}, {key9=value9}, {key10=value10}]
Step #1: [{key11=value11}, {key12=value12}, {key13=value13}, {key14=value14}, {key15=value15}, {key16=value16}, {key17=value17}, {key18=value18}, {key19=value19}, {key20=value20}]
Step #2: [{key21=value21}, {key22=value22}, {key23=value23}, {key24=value24}, {key25=value25}, {key26=value26}, {key27=value27}, {key28=value28}, {key29=value29}, {key30=value30}]
Step #3: [{key31=value31}, {key32=value32}]
Step #4: []
Done

如您所见,这真的很容易。

于 2018-06-07T10:46:39.960 回答