🦔

PythonでJSONを扱いたい時に見る記事

2024/10/20に公開

PythonでJSONを扱う時、違うメソッドを使用してエラーが出たり、引数の設定について毎回調べていたため備忘録も兼ねて記事にしました。

参考

https://docs.python.org/ja/3/library/json.html

バージョン

  • Python 3.10.14

概要

以下のテーブルは、本記事で扱う4つの主要なメソッドの概要を示しています。

メソッド 説明 入力 出力
json.dump() PythonオブジェクトをファイルにJSON形式で書き込む Pythonオブジェクト&fp(ファイルポインタ) なし(ファイルに書き込み)
json.dumps() PythonオブジェクトをJSON形式の文字列に変換する Pythonオブジェクト JSON文字列
json.load() JSONファイルからPythonオブジェクトを読み込む fp(ファイルポインタ) Pythonオブジェクト
json.loads() JSON形式の文字列をPythonオブジェクトに変換する JSON文字列 Pythonオブジェクト

PythonオブジェクトからJSONへの変換はdump,dumps

json.dump(): オブジェクトをJSONファイルに書き込む

Pythonのオブジェクトをファイルに(JSON形式で)書き込むための関数です。オブジェクトをJSON形式のfpへのストリームとして変換します。

  1. 関数の定義
def dump(obj, fp, *, skipkeys=False, ensure_ascii=True, check_circular=True,
        allow_nan=True, cls=None, indent=None, separators=None,
        default=None, sort_keys=False, **kw):
  1. 使い方
main.py
import json

# サンプルデータを作成
data = {
    "名前": "山田太郎",
    "年齢": 30,
}

# JSONファイルに書き込む
with open('data.json', 'w', encoding='utf-8') as fp:
    json.dump(data, fp, ensure_ascii=False, indent=4)
  1. 出力結果(jsonファイル)
data.json
{
    "名前": "山田太郎",
    "年齢": 30
}

fpfile pointerの略で、データを書き込めるもの全般を指しています。例えば、open()関数でファイルを開くと、ファイルオブジェクトが返され、そのオブジェクトが「fp」と呼ばれることがあります。また、StringIOBytesIOfpとして扱われます。
ここで扱うことができるfpは.write()がサポートされているものを指します。

引数で設定できる値

引数 デフォルト値 説明
obj - JSONに変換したいPythonオブジェクト。辞書、リスト、文字列、数値などが対象。
fp - "file pointer"の略。.write()メソッドを持つファイルライクなオブジェクト。通常はopen()で開いたファイルオブジェクトを指定。
skipkeys False Trueにすると、辞書のキーが文字列や数値以外の場合、エラーを出さずにスキップする。
ensure_ascii True Trueだと、非ASCII文字をエスケープする。Falseなら、そのまま出力する。
check_circular True 循環参照をチェックするかどうか。Falseにすると高速化するが、循環参照があるとエラーになる。
allow_nan True Trueなら、非数(NaN)や無限大(Infinity)をJavaScriptの表現で出力する。Falseだとエラーになる。
indent None インデントのレベルを指定。Noneだとインデント無し、数字ならそのスペース数、文字列ならその文字でインデントする。
separators - 項目と項目の区切り文字、キーと値の区切り文字をタプルで指定する。
default - JSONに直接変換できないオブジェクトを変換するための関数を指定する。
sort_keys False Trueにすると、辞書のキーをソートして出力する。
cls - JSONEncoderのサブクラスを指定して、エンコードの挙動をカスタマイズできる。

json.dumps(): オブジェクトをJSON形式の文字列に変換

json.dumps()PythonのオブジェクトをJSON形式の文字列に変換する関数です。

  1. 関数の定義
def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True,
        allow_nan=True, cls=None, indent=None, separators=None,
        default=None, sort_keys=False, **kw):
  1. 使い方
main.py
import json

# サンプルデータを作成
data = {
    "名前": "山田太郎",
    "年齢": 30,
}

# JSON文字列を作成
json_str = json.dumps(data, ensure_ascii=False, indent=4)
print(json_str)
  1. 出力結果
{
    "名前": "山田太郎",
    "年齢": 30
}

引数で設定できる値

json.dump()とほぼ同じため省略。

JSONからPythonオブジェクトへの変換はload,loads

json.load(): JSONファイルからPythonオブジェクトを読み込む

json.load()JSONファイルからデータを読み込み、Pythonオブジェクトに変換する関数です。

  1. 関数の定義
def load(fp, *, cls=None, object_hook=None, parse_float=None,
        parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
  1. 使い方
main.py
import json

# JSONファイルから読み込む
with open('data.json', 'r', encoding='utf-8') as fp:
    data = json.load(fp)

print(data)
print(type(data))
  1. 入力ファイル(JSONファイル)
data.json
{
    "名前": "山田太郎",
    "年齢": 30
}
  1. 出力結果
{'名前': '山田太郎', '年齢': 30}
<class 'dict'>

引数で設定できる値

引数 デフォルト値 説明
fp - JSONデータを含むファイルオブジェクト。.read()メソッドをサポートしている必要がある。
cls None JSONDecoderのサブクラスを指定して、デコードの挙動をカスタマイズできる。
object_hook None デコードされた辞書に対して呼び出される関数。戻り値が辞書の代わりに使用される。
parse_float None JSONの浮動小数点数をデコードする際に使用する関数。デフォルトはfloat()
parse_int None JSONの整数をデコードする際に使用する関数。デフォルトはint()
parse_constant None -Infinity, Infinity, NaNをデコードする際に使用する関数。
object_pairs_hook None object_hookと似ているが、順序付きリストのペアに対して呼び出される。優先度はobject_hookより高い。

注意点

  • 入力ファイルのエンコーディングはUTF-8、UTF-16、UTF-32のいずれかである必要があります。
  • バイナリファイルも読み込めますが、エンコーディングに注意が必要です。
  • 不正なJSONドキュメントを読み込もうとすると、JSONDecodeErrorが発生します。

json.loads(): JSON形式の文字列をPythonオブジェクトに変換

json.loads()JSON形式の文字列をPythonオブジェクトに変換する関数です。

  1. 関数の定義
def loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
  1. 使い方
main.py
import json

# JSON形式の文字列
json_str = '{"名前": "山田太郎", "年齢": 30}'

# JSON文字列をPythonオブジェクトに変換
data = json.loads(json_str)

print(data)
print(type(data))
  1. 出力結果
{'名前': '山田太郎', '年齢': 30}
<class 'dict'>

引数で設定できる値

json.load()とほぼ同じため省略。

注意点

  • 入力文字列のエンコーディングはUTF-8、UTF-16、UTF-32のいずれかである必要があります。
  • bytes型やbytearray型の入力も受け付けますが、エンコーディングに注意が必要です。
  • 不正なJSON文字列を変換しようとすると、JSONDecodeErrorが発生します。
  • Python 3.9以降では、encodingキーワード引数は削除されています。

(番外編)JSONを読み込んで、定義したclassに適用させたい場合

**dataは辞書のキーと値をそれぞれ引数名と値として展開します。これを利用して、classに一発で適用させます。

main.py
import json
from dataclasses import dataclass


@dataclass
class Person:
    name: str
    age: int


json_string = '{"name": "山田太郎", "age": 30}'

# 直接Personクラスのインスタンスに変換
data = json.loads(json_string)
person = Person(**data)

# 結果を表示
print(person)
print(type(person))

出力結果

Person(name='山田太郎', age=30)
<class '__main__.Person'>

注意点

  • JSONのキーとクラスの属性名が完全に一致している必要があります。
  • より複雑なデータ構造や、ネストされたオブジェクトがある場合は、追加の処理が必要になる可能性があります。

Discussion