Keep on moving

あんまりまとまってないことを書きますよ

PythonでJSON Linesを扱う

key value
Python 3.8 or later
Last Update 2020/09/06

こんにちは、yaml苦手っ子です。PythonJSON Linesを扱う方法を調べたのでまとめておきます。

JSON Lines とは

JSONを行区切りでファイルに書き込んだものです。

JSON Lines ここによると以下が条件みたいです.

  1. UTF-8 Encoding
  2. Each Line is a Valid JSON Value
  3. Line Separator is '\n'

Python での扱い方

ファイルから読んで、一行ごとにばらして json.load する感じです。 コードで書くとこんな感じです。

import json
from typing import Any, Dict, Iterator, List, TextIO


def filter_not_empty(list: List[str]) -> Iterator[str]:
    return filter(lambda x: len(x) > 0, list)


# TODO: DictではなくTypedDictを使うと型ヒントの恩恵に預かれて便利
def parse_jsonl(fp: TextIO) -> List[Dict[str, Any]]:
    # fileが空行を含むことがあるので念の為フィルターする
    jlines = filter_not_empty(fp.read().splitlines())
    result = [json.loads(jline) for jline in jlines]
    return result


if __name__ == "__main__":
    with open("sample.jsonl", "r") as json_file:
        print(parse_jsonl(json_file))

jqコマンドの代わりにPythonJSON Linesをpretty printする

Python 3.8から json.toolでもJSON Linesに対応しました。こんな感じでつかえます。

json --- JSON エンコーダおよびデコーダ — Python 3.8.5 ドキュメント

$ python3.8 -mjson.tool --json-lines sample.jsonl 
{
    "name": "Gilbert",
    "wins": [
        [
            "straight",
            "7\u2663"
        ],
        [
            "one pair",
            "10\u2665"
        ]
    ]
}
{
    "name": "Alexa",
    "wins": [
        [
            "two pair",
            "4\u2660"
        ],
        [
            "two pair",
            "9\u2660"
        ]
    ]
}
{
    "name": "May",
    "wins": []
}
{
    "name": "Deloise",
    "wins": [
        [
            "three of a kind",
            "5\u2663"
        ]
    ]
}

先人に感謝します。