Tôi sẽ đề nghị xem Jackson Api rất dễ dàng để kết hợp các tùy chọn phân tích cú pháp luồng và mô hình cây: bạn có thể di chuyển toàn bộ tệp theo cách phát trực tuyến rồi đọc từng đối tượng vào một cây kết cấu.
Là một example, chúng ta hãy đầu vào sau:
{
"records": [
{"field1": "aaaaa", "bbbb": "ccccc"},
{"field2": "aaa", "bbb": "ccc"}
] ,
"special message": "hello, world!"
}
Chỉ cần tưởng tượng các lĩnh vực là thưa thớt hoặc các hồ sơ có một cấu trúc phức tạp hơn.
Đoạn mã sau đây minh họa cách có thể đọc tệp này bằng cách kết hợp phân tích luồng và mô hình cây. Mỗi bản ghi riêng lẻ được đọc trong cấu trúc cây, nhưng tệp này không bao giờ được đọc toàn bộ vào bộ nhớ, làm cho nó có thể xử lý các tệp JSON có kích thước gigabyte trong khi sử dụng bộ nhớ tối thiểu.
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();
}
}
}
}
Như bạn có thể đoán, các nextToken() gọi mỗi lần cung cấp cho các sự kiện phân tích tiếp theo: bắt đầu đối tượng, bắt đầu lĩnh vực, bắt đầu mảng, bắt đầu đối tượng, ..., đối tượng cuối, ..., mảng cuối , ...
Cuộc gọi jp.readValueAsTree()
cho phép đọc nội dung ở vị trí phân tích cú pháp hiện tại, đối tượng hoặc mảng JSON, thành mô hình cây JSON chung của Jackson. Khi bạn có điều này, bạn có thể truy cập dữ liệu ngẫu nhiên, bất kể thứ tự xuất hiện trong tệp (trong ví dụ field1 và field2 không phải lúc nào cũng theo thứ tự). Jackson cũng hỗ trợ ánh xạ lên các đối tượng Java của riêng bạn. Các jp.skipChildren() là thuận tiện: nó cho phép bỏ qua một cây đối tượng hoàn chỉnh hoặc một mảng mà không cần phải chạy cho mình trên tất cả các sự kiện chứa trong nó.
Giải pháp thay thế Java EE: javax.json.stream.JsonParser – xonya