列名をJSONのキーにし、各セルは文字列のまま保持します。ensure_ascii=Falseで日本語をそのまま書き出し、重複した列名や列数不一致は変換前に止めます。
この記事の内容
対象・検証範囲:CPython 3.12.14 / Linux。掲載サンプルと期待する出力を照合。標準ライブラリのみ。
変換後の型を先に決める
CSVの001をJSONの数値1へ変えると、識別子の先頭ゼロが失われます。この例ではすべての値を文字列にし、空セルも空文字列のまま出力します。空セルをnullにする処理や数値化は行いません。
前提はヘッダーが1行あり、各列名が一意で、全レコードの列数が同じCSVです。列名が重複すると、JSONの同じキーへ値を詰めるときに情報を失うため、エラーにします。
変換コード
サンプルは標準ライブラリだけで動き、外部サービスへデータを送信しません。CSV文字列を関数へ渡し、JSON文字列を受け取ります。
import csv
import io
import json
def csv_to_json(text):
reader = csv.reader(io.StringIO(text, newline=""), strict=True)
header = next(reader, None)
if not header or any(not name.strip() for name in header):
raise ValueError("空のヘッダーまたは列名があります")
if len(set(header)) != len(header):
raise ValueError("列名が重複しています")
records = []
for row in reader:
if not row:
continue
if len(row) != len(header):
raise ValueError("列数が一致しません")
records.append(dict(zip(header, row)))
return json.dumps(records, ensure_ascii=False, indent=2)
result = csv_to_json("id,name,note\n001,ノート,\n")
print(result)
restored = json.loads(result)
assert restored[0]["id"] == "001"
assert restored[0]["note"] == ""
try:
csv_to_json("id,id\n001,002\n")
except ValueError as error:
print(error)
期待する結果と保存方法
[
{
"id": "001",
"name": "ノート",
"note": ""
}
]
列名が重複しています
日本語がそのまま見えるのはensure_ascii=Falseのためです。JSONで日本語が\u形式のエスケープで保存されていても、それだけで文字化けとはいえません。JSONとして読み直した値が一致するかを確認します。
ファイルとして使う場合は入力CSVの文字コードを指定して読み、返った結果をUTF-8の新しい.jsonファイルへ保存します。open("output.json", "x", encoding="utf-8")なら既存ファイルの上書きを避けられます。ヘッダーだけのCSVは空配列になります。
数値や日付を自動変換しない理由
2026-09-20は日付らしく見えますが、JSONに標準の日付型はありません。001も計算する数値か、商品コードかは列の仕様によります。
数値変換が必要なら対象列を指定し、変換できない値の扱いを決めてから追加します。「数字だけだから数値」という一律の推測は、IDや長い番号を壊す原因になります。入力の意味はJSONへ変換するだけでは確定しません。
制限と次に確認すること
このコードはJSON全体をメモリー上に作ります。大きなデータではJSON Linesなど別の形式や、分割処理が必要です。また、CSVの空行を無視するため、空行自体が意味を持つ独自形式には使えません。
JSONのキーとして使えることと、連携先がその列名を受け付けることは別です。連携先の必須項目・型・上限も確認し、CSVの構造検査と組み合わせてください。
参考にした公式資料
- Python公式: json — JSONのエンコードとデコード確認日:2026.09.20
- Python公式: csv — CSVファイルの読み書き確認日:2026.09.20
掲載サンプルは記載のPython環境で実行確認しています。すべてのOS・入力データを保証するものではありません。 編集・検証方針