Предлагаю взглянуть на Jackson Api , очень легко объединить параметры потоковой передачи и анализа древовидной модели: вы можете перемещаться по файлу в целом потоковым способом, а затем читать отдельные объекты в древовидную структуру.
В качестве примера , давайте возьмем следующий ввод:
{
"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 Джексона. Если у вас есть это, вы можете получить доступ к данным в произвольном порядке, независимо от того, в каком порядке они появляются в файле (в примере field1 и field2 не всегда находятся в одинаковом порядке). Джексон также поддерживает отображение на ваши собственные объекты Java. Jp.skipChildren () удобен: он позволяет пропускать полное дерево объектов или массив без необходимости запускать все события, содержащиеся в нем.