处理大型 JSON 文件的 5 种方法与工具推荐
当 JSON 文件达到 GB 级别时,传统的 JSON.parse() 会导致内存溢出。本文介绍 5 种处理大型 JSON 文件的高效方法。
问题:为什么大 JSON 文件难处理?
假设一个 2GB 的 JSON 文件:
- 内存占用:解析后可能占用 4-6GB 内存
- 解析时间:
JSON.parse()可能耗时 30 秒以上 - UI 阻塞:前端解析会冻结页面
方法一:流式解析(Streaming)
不一次性加载整个文件,而是逐块读取和处理。
JavaScript 实现
const { createReadStream } = require('fs');
const { parser } = require('stream-json');
const { streamArray } = require('stream-json/streamers/StreamArray');
const pipeline = createReadStream('large.json')
.pipe(parser())
.pipe(streamArray());
pipeline.on('data', ({ key, value }) => {
// 逐条处理,内存占用极低
console.log(key, value);
});
Java 实现(Jackson Streaming)
JsonFactory factory = new JsonFactory();
try (JsonParser parser = factory.createParser(new File("large.json"))) {
while (parser.nextToken() != null) {
// 逐 token 处理
if (parser.currentToken() == JsonToken.START_OBJECT) {
// 处理对象
}
}
}
方法二:JSON Lines 格式
将大 JSON 数组转换为 JSON Lines(每行一个 JSON 对象)。
{"id": 1, "name": "张三"}
{"id": 2, "name": "李四"}
{"id": 3, "name": "王五"}
优势:
- 可以逐行读取,无需解析整个文件
- 支持 grep、awk 等命令行工具
- 可以并行处理
方法三:使用 jq 命令行工具
jq 是处理 JSON 的瑞士军刀,适合大文件。
# 提取特定字段
cat large.json | jq '.[] | .name'
# 过滤数据
cat large.json | jq '.[] | select(.age > 25)'
# 统计数量
cat large.json | jq 'length'
# 内存优化:使用 --stream
cat large.json | jq --stream 'select(.[0][-1] == "name") | .[1]'
方法四:分块处理
将大文件分割成小块分别处理。
import json
def process_large_json(filename):
with open(filename, 'r') as f:
data = json.load(f)
# 分批处理
batch_size = 1000
for i in range(0, len(data), batch_size):
batch = data[i:i+batch_size]
process_batch(batch)
方法五:使用数据库
将 JSON 数据导入数据库,使用 SQL 查询。
# 使用 SQLite
sqlite3 data.db "CREATE TABLE json_data (data TEXT);"
# 导入数据后用 SQL 查询
# 使用 MongoDB
mongoimport --db test --collection users --file large.json --jsonArray
工具推荐
| 工具 | 适用场景 | 特点 |
|---|---|---|
| jq | 命令行处理 | 轻量、强大 |
| fx | 交互式浏览 | 可视化 |
| JSON Lines | 大数据处理 | 流式友好 |
| Jackson Streaming | Java 项目 | 高性能 |
| ijson | Python 项目 | 流式解析 |
最佳实践
- 预防为主:API 设计时避免返回超大 JSON
- 分页:使用分页返回数据,每页 100-1000 条
- 压缩:传输时使用 Gzip 压缩
- 监控:监控 JSON 大小,设置告警阈值
总结
处理大型 JSON 文件的关键是避免一次性加载整个文件。流式解析、JSON Lines、分块处理等方法可以有效降低内存占用,提升处理效率。