0xf

日記だよ

load_table_from_json の第一引数が json でも jsonl でもない件について

google.cloud.bigquery.client.Clientload_table_from_json について。

googleapis.dev

BQにデータ突っ込むスクリプトで、一時ファイル作りたくなくて、load_table_from_json を使おうとして少しハマっていた。

第一引数は json_rows と仮引数名設定されていたのでてっきり、json文字列のリスト的なものを渡せばよいのだろうと思い、

def jsonRows(items):
  return [json.dumps(item) for item in items]

みたいにやって

google.api_core.exceptions.BadRequest: 400 Error while reading data, error message: Failed to parse JSON: No active field found.; ParsedString returned false

と怒られていたのだけど、なんのことはなくて、よくシグネチャを見ると第一引数は json_rows: Iterable[Dict[str, Any]] なのだった。

お前 json ぜんぜん関係ねえじゃん。 jsonl にシリアライズできる必要がある、と言い張るとしても無理がある。

結果。以下だいたい公式のサンプルコード通り。

import json
import sys

from google.cloud import bigquery

client = bigquery.Client()

# TODO: プロジェクトごとに修正する
table_id = "your_project.your_dataset.your_table"

# auto detect でスキーマの自動推測
# WRITE_TRUNCATE で一回ごとにテーブルを作り直す。
# WRITE_APPENDは追加、WRITE_EMPTYは空だったら書き込みをする
job_config = bigquery.LoadJobConfig(
    source_format=bigquery.SourceFormat.NEWLINE_DELIMITED_JSON,
    autodetect=True,
    write_disposition=bigquery.WriteDisposition.WRITE_TRUNCATE
)

# json シリアライズ可能な Dict のイテレータ
rows = [{"name": "tom1", "age": 19}, {
    "name": "tom2", "age": 20}, {"name": "tom3", "age": 21}]

job = client.load_table_from_json(
    rows, table_id, job_config=job_config)

job.result()  # ジョブの終了を待つ

table = client.get_table(table_id)  # テーブルの情報を取得
print(
    "Loaded {} rows and {} columns to {}".format(
        table.num_rows, len(table.schema), table_id
    ),
    file=sys.stderr
)