2022年12月17日土曜日

Pythonでdataclassを使ってdictからオブジェクトに変換する方法

Pythonでdataclassを使ってdictからオブジェクトに変換する方法

概要

過去にmarshmallowを使った方法を紹介しました
今回はサードパーティのライブラリは使わずに dataclass だけを使って変換する方法を紹介します

環境

  • Ubuntu18.04
  • Python 3.10.2

サンプルコード

from dataclasses import dataclass

@dataclass
class Profile():
    lang: str
    framework: str

@dataclass
class User():
    name: str
    age: int
    profile: Profile


if __name__ == "__main__":
    dict_data = {
        "name": "hawksnowlog",
        "age": 10,
        "profile": {
            "lang": "ruby",
            "framework": "sinatra"
        }
    }
    user = User(**dict_data)
    print(user.name)
    print(user.age)
    print(user.profile.lang)
    print(user.profile.framework)

しかしこれだとネストしている Profile が展開されず辞書になってしまいます

ネストに対応するには

  • pip install dataclass-wizard
from dataclasses import dataclass

from dataclass_wizard import JSONWizard


@dataclass
class Profile():
    lang: str
    framework: str

@dataclass
class User(JSONWizard):
    name: str
    age: int
    profile: Profile


if __name__ == "__main__":
    dict_data = {
        "name": "hawksnowlog",
        "age": 10,
        "profile": {
            "lang": "ruby",
            "framework": "sinatra"
        }
    }
    user = User.from_dict(dict_data)
    print(user.name)
    print(user.age)
    print(user.profile.lang)
    print(user.profile.framework)

dict に戻すには

to_json メソッドをコールするだけです

from dataclasses import dataclass

from dataclass_wizard import JSONWizard


@dataclass
class Profile():
    lang: str
    framework: str

@dataclass
class User(JSONWizard):
    name: str
    age: int
    profile: Profile


if __name__ == "__main__":
    dict_data = {
        "name": "hawksnowlog",
        "age": 10,
        "profile": {
            "lang": "ruby",
            "framework": "sinatra"
        }
    }
    user = User.from_dict(dict_data)
    print(user.name)
    print(user.age)
    print(user.profile.lang)
    print(user.profile.framework)
    print(user.to_json())

datetime の使い方

from datetime import datetime
from dataclasses import dataclass

from dataclass_wizard import JSONWizard


@dataclass
class Profile():
    lang: str
    framework: str

@dataclass
class User(JSONWizard):
    name: str
    age: int
    created_at: datetime
    profile: Profile


if __name__ == "__main__":
    dict_data = {
        "name": "hawksnowlog",
        "age": 10,
        "created_at": "2010-06-10 15:50:00Z",
        "profile": {
            "lang": "ruby",
            "framework": "sinatra"
        }
    }
    user = User.from_dict(dict_data)
    print(user.name)
    print(user.age)
    print(user.created_at.year)
    print(user.profile.lang)
    print(user.profile.framework)
    print(user.to_json())

最後に

結局 pypi から追加のライブラリが必要になりそうです、、

参考サイト

0 件のコメント:

コメントを投稿