PHP流式读取JSON需借助json-machine或jsonstream等第三方库,避免全量加载;json-machine支持JSONPath路径抽取与SAX式解析,内存占用低,适用于GB级文件及深层嵌套结构提取。

PHP流式读取JSON,核心是避免一次性加载整个文件到内存,适合处理大JSON文件(比如几百MB甚至GB级)。关键在于用 JSON streaming parser 逐段解析,而不是 json_decode(file_get_contents(...)) 这种全量加载方式。
用 jsonstream 或 json-machine 库实现流式解析
PHP原生不支持JSON流式解析,需借助第三方库。推荐两个轻量、稳定、支持SAX式事件驱动的库:
- json-machine(更推荐):纯PHP实现,无依赖,支持 JSON 数组/对象流式遍历,语法简洁,内存占用极低。
- jsonstream:基于 C 扩展(需编译安装),性能略高,但部署稍麻烦。
以 json-machine 为例(通过 Composer 安装):
读取一个大型 JSON 数组(如 [{"id":1,"name":"A"},{"id":2,"name":"B"},...]):
立即学习“PHP免费学习笔记(深入)”;
use JsonMachine\JsonMachine;
$items = JsonMachine::fromFile('large.json', '/'); // '/' 表示根数组
foreach ($items as $item) {
echo $item['id'] . ': ' . $item['name'] . "\n";
// 每次只在内存中保留一个 item,不累积
}
手动流式解析:用 json_decode 配合 fgets 分块读取(仅限简单结构)
如果 JSON 是换行分隔的 JSON Lines(NDJSON)格式,例如:
{"id":1,"name":"A"}{"id":2,"name":"B"}
可用 fgets() 逐行读取 + json_decode() 解析:
$fp = fopen('data.ndjson', 'r');
while (($line = fgets($fp)) !== false) {
$line = trim($line);
if (empty($line)) continue;
$obj = json_decode($line, true);
if (json_last_error() === JSON_ERROR_NONE) {
// 处理 $obj
processItem($obj);
}
}
fclose($fp);
⚠️ 注意:该方法仅适用于每行一个独立 JSON 对象/数组,不适用于嵌套结构或单个大 JSON 文档。
处理深层嵌套 JSON 的流式抽取(如提取所有 "user.name")
若需从巨型 JSON 中提取特定路径(如 $.store.book[*].author),json-machine 支持 JSONPath 表达式:
use JsonMachine\JsonMachine;
// 只提取所有 author 字段,跳过其余内容
$authors = JsonMachine::fromFile('big.json', '$.store.book[*].author');
foreach ($authors as $author) {
echo $author . "\n"; // 每次只解析匹配路径,不加载整棵树
}
它底层按需解析 Token,遇到匹配路径才构建 PHP 值,极大节省内存。
注意事项与避坑点
- 确保 JSON 格式合法;流式解析器对格式错误更敏感,建议先用
jq -n 'true' 或在线工具校验。 - 不要在循环中反复
fopen/fclose同一文件;保持句柄打开,让库内部管理读取位置。 - 避免在流式循环里做耗时操作(如 DB 写入),可批量缓存后提交,防止阻塞 I/O。
- Windows 下注意文件编码(UTF-8 无 BOM),BOM 会导致 JSON 解析失败。



















