Я предлагаю взглянуть на Jackson Api, очень просто объединить варианты анализа потоков и древовидной модели: вы можете перемещаться по файлу в целом потоковым способом, а затем читать отдельные объекты в дерево состав.
Как example, давайте рассмотрим следующий вход:
{
"records": [
{"field1": "aaaaa", "bbbb": "ccccc"},
{"field2": "aaa", "bbb": "ccc"}
] ,
"special message": "hello, world!"
}
Только представьте поля, скудно или записи, имеющие более сложную структуру.
Следующий фрагмент иллюстрирует, как этот файл может быть прочитан с использованием комбинации анализа потока и древовидной модели. Каждая отдельная запись считывается в древовидной структуре, но файл никогда не читается целиком в памяти, что позволяет обрабатывать файлы JSON размером с гигабайт при минимальной памяти.
import org.codehaus.jackson.map.*;
import org.codehaus.jackson.*;
import java.io.File;
public class ParseJsonSample {
public static void main(String[] args) throws Exception {
JsonFactory f = new MappingJsonFactory();
JsonParser jp = f.createJsonParser(new File(args[0]));
JsonToken current;
current = jp.nextToken();
if (current != JsonToken.START_OBJECT) {
System.out.println("Error: root should be object: quiting.");
return;
}
while (jp.nextToken() != JsonToken.END_OBJECT) {
String fieldName = jp.getCurrentName();
// move from field name to field value
current = jp.nextToken();
if (fieldName.equals("records")) {
if (current == JsonToken.START_ARRAY) {
// For each of the records in the array
while (jp.nextToken() != JsonToken.END_ARRAY) {
// read the record into a tree model,
// this moves the parsing position to the end of it
JsonNode node = jp.readValueAsTree();
// And now we have random access to everything in the object
System.out.println("field1: " + node.get("field1").getValueAsText());
System.out.println("field2: " + node.get("field2").getValueAsText());
}
} else {
System.out.println("Error: records should be an array: skipping.");
jp.skipChildren();
}
} else {
System.out.println("Unprocessed property: " + fieldName);
jp.skipChildren();
}
}
}
}
Как вы можете догадаться, nextToken() вызов каждый раз дает следующее событие разбора: запуск объекта, запуск поле, запуск массива, запуск объекта, ..., конечный объект, ..., конец массива , ...
Звонок jp.readValueAsTree()
позволяет читать то, что находится в текущей позиции синтаксического анализа, объект или массив JSON, в дженерическую модель JSON Jackson. После этого вы можете получить доступ к данным случайным образом, независимо от порядка, в котором вещи появляются в файле (в поле примера1 и поле2 не всегда находятся в одном порядке). Джексон также поддерживает отображение на ваши собственные объекты Java. Jp.skipChildren() удобен: он позволяет пропустить полное дерево объектов или массив без необходимости запускаться над всеми событиями, содержащимися в нем.
Альтернатива Java EE: javax.json.stream.JsonParser – xonya