こんにちは。
はけです。

python3.7から使えるようになったdataclass。
データの箱を示すクラスを用意するときにとても重宝します。

本記事は、次のような方を対象にしています。

  • dataclassをdictやjsonに変換したい!
  • jsonやdictをdataclassに変換したい!

dataclassのデータを使って処理を行うときや、出力用のフォーマットに整形するようなとき、データの変換を行う必要があります。

そんなデータの変換について、本記事ではdictや jsonへ相互に変換する方法を解説します。

特に、json形式のリクエストをAPIで受け取るときや、DBから情報を取得するときに使用します。

覚えてしまえば簡単にできてしまいます。
ぜひ試してみてくださいね!

pythonのdataclassをdictやjsonに相互変換する

dataclassをdictやjsonに相互変換する方法を解説していきます。

実行環境

  • Windows10
  • python3.9.1
  • dataclasses-json0.5.2

dataclassを使う理由

dataclassはpython3.7から使えるようになり、データの箱を表現するためにとても便利なクラスです。

たくさんメリットがありますが、大きなメリットは次になります。

  • クラスがデータの箱であることが明示できる
  • クラスの初期化を簡単に実装できる

本記事ではあまり詳しいことは書きませんが、データの箱としてかなり優秀なクラスがdataclassになります。

今回のサンプルプログラムではjsonやdictなどのデータがネストできることも考慮し、ネストしたdataclassで試しています。

 

from dataclasses import dataclass, field
from typing import List

@dataclass
class SampleInfoChild:
    """ Sample情報子データクラス
    """
    childint: int = 0
    childstr: str = ''

@dataclass
class SampleInfoParent:
    """ Sample情報親データクラス
    """
    data1: int = 0
    data2: str = ''
    data3: float = 0.0
    listint: List[int] = field(default_factory=list)
    childobj: SampleInfoChild = None

SampleInfoParentがメインのクラス、SampleInfoChildがネストされたクラスになります。

それぞれのクラスの頭に「@dataclass」をつけることでdataclassであることを定義できます。

childobjにSampleInfoChild型を設定することでネストしたクラスを定義することができます。

では、さっそくdataclassの変換方法を解説していきます!

dataclassをdictに変換する方法

まずはdataclassをdictに変換する方法を解説していきます。

dataclassをdictに変換するときは標準機能に搭載されているdataclassesのasdictを使用します。

from dataclasses import dataclass, field, asdict
from typing import List

@dataclass
class SampleInfoChild:
    """ Sample情報子データクラス
    """
    childint: int = 0
    childstr: str = ''

@dataclass
class SampleInfoParent:
    """ Sample情報親データクラス
    """
    data1: int = 0
    data2: str = ''
    data3: float = 0.0
    listint: List[int] = field(default_factory=list)
    childobj: SampleInfoChild = None

sample = SampleInfoParent(2, 'abc', 2.5, [123, 234], SampleInfoChild(2, 'ddd'))
print(asdict(sample)) # ★

単純にSampleInfoParentクラスを初期化後、asdictでdictに変換しています。

結果を見てみると、次のようになります。

{'data1': 2, 'data2': 'abc', 'data3': 2.5, 'listint': [123, 234], 'childobj': {'childint': 2, 'childstr': 'ddd'}}

しっかりすべての変数が変換できていることがわかります。

このように、簡単にdictに変換することができます。

dictからdataclassに変換する方法

次はdictからdataclassに変換する方法を解説していきます。

dictからdataclassに変換するときは、dictを展開することで初期化することができます。

from dataclasses import dataclass, field
from typing import List

@dataclass
class SampleInfoChild:
    """ Sample情報子データクラス
    """
    childint: int = 0
    childstr: str = ''

@dataclass
class SampleInfoParent:
    """ Sample情報親データクラス
    """
    data1: int = 0
    data2: str = ''
    data3: float = 0.0
    listint: List[int] = field(default_factory=list)
    childobj: SampleInfoChild = None

dict = {'data1':2, 'data2':'abc', 'data3':2.5,
        'listint':[123, 234], 'childobj': {'childint':2, 'childstr':'ddd'}}
sample = SampleInfoParent(**dict) # ★
print(sample)

dictを作成しておきます。キー名やネストの構成は同じにする必要があります。

**dictをクラスの初期化時に渡すことで、変換が実現できます。

結果を見てみると、次のようになります。

SampleInfoParent(data1=2, data2='abc', data3=2.5, listint=[123, 234], childobj={'childint': 2, 'childstr': 'ddd'})

クラスの情報がすべて作成されています。

 

dataclassをjsonに変換する方法

次はdataclassをjsonに変換する方法を解説していきます。

jsonに変換するときに、外部ライブラリのdataclasses-jsonが必要になります。

以下のコマンドでライブラリをインストールしてください。

pip install dataclasses-json

 

インストールができたら、次のようにto_jsonを使用してdataclassをjsonに変換することができます。

from dataclasses import dataclass, field
from typing import List
from dataclasses_json import dataclass_json # ★

@dataclass_json # ★
@dataclass
class SampleInfoChild:
    """ Sample情報子データクラス
    """
    childint: int = 0
    childstr: str = ''

@dataclass_json # ★
@dataclass
class SampleInfoParent:
    """ Sample情報親データクラス
    """
    data1: int = 0
    data2: str = ''
    data3: float = 0.0
    listint: List[int] = field(default_factory=list)
    childobj: SampleInfoChild = None

sample = SampleInfoParent(2, 'abc', 2.5, [123, 234], SampleInfoChild(2, 'ddd'))
print(sample)
print(sample.to_json(indent=4, ensure_ascii=False)) # ★

★部分が変更箇所になります。

以下のような実装を加えました。

  • dataclasses_jsonをimportしました
  • 各dataclassに@dataclass_jsonのデコレータを加えました
  • 最後にto_jsonでjson文字列に変換しました

結果を見てみると、次のようになります。

{
    "data1": 2,
    "data2": "abc",
    "data3": 2.5,
    "listint": [
        123,
        234
    ],
    "childobj": {
        "childint": 2,
        "childstr": "ddd"
    }
}

json形式の文字列が出力されます。

 

jsonからdataclassに変換する方法

最後にjsonからdataclassに変換する方法を解説していきます。

次のようにfrom_jsonを使用してjsonからdataclasssに変換することができます。

from dataclasses import dataclass, field
from typing import List
from dataclasses_json import dataclass_json

@dataclass_json
@dataclass
class SampleInfoChild:
    """ Sample情報子データクラス
    """
    childint: int = 0
    childstr: str = ''

@dataclass_json
@dataclass
class SampleInfoParent:
    """ Sample情報親データクラス
    """
    data1: int = 0
    data2: str = ''
    data3: float = 0.0
    listint: List[int] = field(default_factory=list)
    childobj: SampleInfoChild = None

jsonstr = '''{"data1":2, "data2":"abc", "data3":2.5,
        "listint":[123, 234], "childobj": {"childint":2, "childstr":"ddd"}}'''

sample = SampleInfoParent.from_json(jsonstr) # ★
print(sample)

★部分が変更箇所になります。

dataclass.from_jsonでjsonからdataclassに変換することができます。

結果を見てみると、次のようになります。

SampleInfoParent(data1=2, data2='abc', data3=2.5, listint=[123, 234], childobj=SampleInfoChild(childint=2, childstr='ddd'))

しっかりとdataclassの情報が取り込まれました。

 

以上が、dataclassからdictやjsonを相互変換する方法の解説となります。

まとめ

本記事では以下のことを解説しました。

  • dataclassからdictに変換する方法
  • dictからdataclassに変換する方法
  • dataclassからjsonに変換する方法
  • jsonからdataclassに変換する方法

jsonを相互変換する場合は、「dataclasses-json」を取り込むことで変換することができるようになりました。

ぜひ参考に、dataclassを使ってみてください!

以上がdataclassをdictやjsonと相互に変換する方法となります。

本ブログでは、主にPythonの環境設定やコーディングの方法について、初心者~中級者向けに解説しています。

興味がある方は、他の記事も参考にしてみてください!!