前回の記事では、@dataclass
を使って __init__()
を自動生成する仕組みや、コンストラクター引数の扱いについてまとめました。
今回はその続きとして、dataclassインスタンスを辞書に変換する方法(asdict()
)や、JSONとして保存・送信する方法(シリアライズ)について、自分の理解を整理しておきます。
辞書に変換する:asdict()
まず、dataclass
を辞書に変換したいときは、標準ライブラリ dataclasses
の asdict()
を使います。
from dataclasses import dataclass, asdict
@dataclass
class User:
name: str
age: int
user = User("Riku", 28)
user_dict = asdict(user)
print(user_dict) # {'name': 'Riku', 'age': 28}
ポイント:
-
asdict()
は再帰的に変換されるので、入れ子になった dataclass も対応してくれます。 - 返り値は Python の通常の辞書(
dict
型)になります。
JSONに変換する(シリアライズ)
Pythonの辞書を JSON に変換するには、標準ライブラリの json.dumps()
を使います。
つまり、asdict()
と組み合わせることで dataclass も JSON に変換できます。
import json
from dataclasses import dataclass, asdict
@dataclass
class Product:
name: str
price: int
p = Product("Headphones", 15000)
# 辞書に変換してからJSONに変換
json_str = json.dumps(asdict(p), ensure_ascii=False)
print(json_str) # {"name": "Headphones", "price": 15000}
ensure_ascii=False
を使うと、日本語なども文字化けせずに表示されます。
ネストされた dataclass にも対応できる
入れ子構造(ネスト)になった dataclass も、asdict()
で辞書に変換できます。
from dataclasses import dataclass, asdict
@dataclass
class Author:
name: str
age: int
@dataclass
class Book:
title: str
author: Author
b = Book("Python入門", Author("Suzuki", 40))
print(asdict(b))
# {'title': 'Python入門', 'author': {'name': 'Suzuki', 'age': 40}}
asdict()
は内部の dataclass も自動的に辞書化してくれます。
JSONから復元(逆変換)するには?
Pythonの辞書から dataclass インスタンスを作りたいときは、**辞書展開
を使います。
from dataclasses import dataclass
@dataclass
class Item:
id: int
name: str
item_dict = {"id": 1, "name": "Monitor"}
item = Item(**item_dict)
print(item) # Item(id=1, name='Monitor')
もし JSON 文字列から復元したい場合は、まず json.loads()
で辞書にしてから展開します。
import json
from dataclasses import dataclass
@dataclass
class Item:
id: int
name: str
json_str = '{"id": 1, "name": "Monitor"}'
item_data = json.loads(json_str)
item = Item(**item_data)
print(item) # Item(id=1, name='Monitor')
ネストが深くなると、自分で中身を展開してあげる必要が出てきますが、シンプルなケースでは **
展開で十分です。
まとめ
-
asdict()
を使えば、dataclass を辞書に変換できる -
json.dumps()
で JSON 文字列として保存・送信できる - JSON → 辞書 → dataclass への復元には
json.loads()
と**kwargs
を使う - ネスト構造も
asdict()
で自動変換されるので扱いやすい