@kyanny's blog

My thoughts, my life. Views/opinions are my own.

Ruby で JSON を SAX っぽく読む

JSON::Stream というライブラリがあった。

github.com

181MB の JSON ファイルをちょっとずつ読んでパースさせてみて、メモリをどのくらい使うか試してみた。比較用に yajl-ruby でパースするのもやってみた。

たしかに省メモリだけど、だいぶ遅い。

yajl-ruby はこれと違って、 mongoexport の –jsonArray オプション無しが出力するような、 JSON オブジェクトが一行ごとに書いてあるようなファイルを省メモリに読むのに向いているようだ。 citylots.json のような単一の巨大な JSON オブジェクトないし Array の場合は、結局パース後のデータは全部丸ごとメモリに載せる必要がある。


昔に仕事で外部のシステムとそこそこの量のデータを毎日ファイルを介して連携するプログラムを書いたことがあった。 CSV にすると将来フォーマットを変えたくなったとき面倒くさいかなと思って JSON を使うことにしたのだけど、 JSON だとサイズが巨大になりすぎたときメモリを使い果たしてパースできなくなるおそれがあるので、データ 1000 件ごとにファイルを変えるというちょっと風変わりなことをした。

ふと、 SAX みたいな API で JSON をパースできれば、ファイルサイズがどれだけ大きくなっても問題ないのでは、と思いついて、調べてみたらそういうライブラリがあったので、いつか使い所があるかなと思いながら試してみたというわけ。

でも、巨大な JSON ファイルを生成するのにもメモリをたくさん使うだろうから、パースできないほど巨大な JSON は作れないので片手落ちかもしれない(文字列連結で頑張れば作れるだろうけど)。


この API で便利そうなのは、巨大な JSON の中から特定の key を持つオブジェクトの中身だけ取出したい、みたいなケースだろうか。 jq みたいな感じ。でもそれだったら jq を使えばよさそう(あっちのほうが早そうだし)。