pythonでJSON Linesを作る方法
前書き
Json Linesというのは以下のような形式です。
{"name":"reimu","score":1} {"name":"marisa","score":1}
JSON Linesに解説されていますが
そんなファイルです。 pysparkのデータ読み込みや、Elasticsearchのbulkでのデータ投入などで使ったりします。
このファイルをPythonを使って作成する方法を示しました。
参考リンク
- JSON Lines
- JSON Linesファイルの定義です。
- json — JSON encoder and decoder — Python 3.9.2 documentation
- pandas.DataFrame.to_json — pandas 1.2.3 documentation
- pandasのto_jsonメソッドの解説リンク。
環境
バージョン | |
---|---|
MacOS Big Sur | 11.1 |
Python3 | 3.9.1 |
pandas | 1.1.4 |
Pythonのみを使う方法
以下のようなデータを用意します。
data_set = [ {'year': '2021', 'month': '01', 'day': '01', 'lang': 'Python', 'note': 'ぱいそん'}, {'year': '2021', 'month': '01', 'day': '01', 'lang': 'Ruby', 'note': 'るびぃ'}, {'year': '2021', 'month': '01', 'day': '01', 'lang': 'C++', 'note': 'しーぷらぷら'} ]
以下のように、リストの中身のオブジェクトを1行ずつ書き出します。
import json with open('test.jsonl', mode='w', encoding='utf-8') as fout: for obj in data_set: json.dump(obj, fout, ensure_ascii=False) fout.write('\n')
上述の、JSON Linesのルールを守るために以下の設定を行っています。
- utf-8エンコーディングを確約するために、open関数でencodingを指定する。
- 1行が一つのjsonとなるように、for文を使いながら毎行、json.dumpを行っています。
- 各行を
\n
で区切っています。最終行の後にも付加されますが、それはどちらでもOKだとJSON Linesに明記されていました。 - 拡張子は
jsonl
にしています。
Pandasを使う方法
こちらの方が圧倒的に簡単です。
以下のようなデータを用意します(上の例と同じ)。
data_set = [ {'year': '2021', 'month': '01', 'day': '01', 'lang': 'Python', 'note': 'ぱいそん'}, {'year': '2021', 'month': '01', 'day': '01', 'lang': 'Ruby', 'note': 'るびぃ'}, {'year': '2021', 'month': '01', 'day': '01', 'lang': 'C++', 'note': 'しーぷらぷら'} ]
以下のように、DataFrameを作ります。
import pandas as pd df = pd.DataFrame(data_set) df ## year month day lang note ## 0 2021 01 01 Python ぱいそん ## 1 2021 01 01 Ruby るびぃ ## 2 2021 01 01 C++ しーぷらぷら
書き出します。
df.to_json('test_pandas.jsonl', force_ascii=False, lines=True, orient='records')
force_asciiについては上述の通りです。
lines=True
とorient=records
パラメータによって、jsonlの形式になります。このことは公式ドキュメント公式ドキュメントのlinesの部分に記述されています。
linesbool, default False If ‘orient’ is ‘records’ write out line delimited json format. Will throw ValueError if incorrect ‘orient’ since others are not list like.
lines=Trueがjsonを1行ずつ出力するjsonlフォーマットのオプションであり、このオプションを正しく動かすために、DataFrameのrowを行として扱うorient=recoresの設定が必要..というイメージだと思います。
出力したjsonlファイルのlint(壊れてないかチェック)
json.toolがコマンドラインインターフェイスを提供しています。利用しているPythonが3.8以上でしたら、jsonだけでなく、jsonlもlintできるオプション--json-lines
が提供されています!
$ python3 -m json.tool --json-lines test.jsonl > /dev/null
jsonlの形式が壊れていたら教えてくれます。
/dev/null
は標準出力を捨てています。jsonlファイルの中身が表示されてしまうため、大きなファイルだと扱いづらいので指定しています。
(jsonの壊れている部分は標準エラーで出力されます)
結論
Pandasを利用できる環境ならPandasを使えば良いと思います。 そうでないならPythonのjsonモジュールで頑張って書き出しましょう。
まとめ
もし、もっと簡単な方法などあればご教授いただけると嬉しいです! 間違いなどへのご指摘もいただけると幸いです。