web-dev-qa-db-ja.com

大きなJSONファイルを解析する

私は、APIにヒットし、JSONファイル(オブジェクトの大きな配列)を受信して​​ローカルに保存するcronスクリプトに取り組んでいます。それが完了すると、ダウンロードしたJSONファイルを別のスクリプトで解析し、各オブジェクトをMySQLデータベースに挿入する必要があります。

現在file_get_contents()json_decode()を使用しています。これは、ファイルを処理する前に、ファイル全体をメモリに読み取ろうとします。私のJSONファイルは通常250MB-1GB +の範囲であるという事実を除いて、これは問題ありません。 PHPメモリ制限を増やすことができることはわかっていますが、それが私の心の中で最大の答えであるとは思われません。fopen()fgets()を使用してファイルを1行ずつ読み取りますが、jsonオブジェクトごとにファイルを読み取る必要があります。

オブジェクトごとにファイルを読み取る方法はありますか、または別の同様のアプローチはありますか?

16
Dan Ramos

これは、jsonファイルに何が含まれているかによります。

ファイルをワンショットでメモリに開くことができない場合、他の唯一のオプションは、ご存知のとおり、fopen/fgetsです。

行ごとの読み取りが可能であり、これらのjsonオブジェクトが一貫した構造を持っている場合は、ファイル内のjsonオブジェクトがいつ開始および終了するかを簡単に検出できます。

オブジェクト全体を収集したら、それをdbに挿入し、次のオブジェクトに進みます。

それ以上のことはありません。 jsonオブジェクトの開始と終了を検出するアルゴリズムは、データソースによっては複雑になる可能性がありますが、以前ははるかに複雑な構造(xml)でこのような処理を行ったため、問題なく動作しました。

6
Kovo

このライブラリを試してください https://github.com/shevron/ext-jsonreader

PHP=に同梱されている既存のext/jsonは非常に便利で使いやすいですが、大量のJSONデータを扱う場合、JSONデータ全体をメモリに読み込む必要があるため、非効率的です(たとえば、file_get_contents()を使用して)PHP変数に一度に変換します-大きなデータセットの場合、これは大量のメモリを消費します。

JSONReaderはメモリ効率を考慮して設計されています-ストリームで機能し、データ全体をメモリにロードすることなく、任意のPHPストリームからJSONデータを読み取ることができます。また、開発者がJSONストリームから特定の値を抽出することもできます。すべてのデータをデコードしてメモリに読み込むことなく。

10
Pawel Dubiel

最善の解決策:

複数のリクエストにわたってデータを小さなチャンクで読み取ることができる、ある種の区切り文字(改ページ、タイムスタンプ、オブジェクトIDなど)を使用します。このソリューションでは、これらのJSONファイルの生成方法をある程度制御できると想定しています。私は次のことを前提にしています。

my JSONファイルは通常250MB-1GB +の範囲になるという事実を除いて、これは問題ありません。

1GBのJSONデータの読み取りと処理は、とんでもないことです。より良いアプローチが絶対に必要です。

4
Wayne Whitty