🛠️

Python の json.load() の結果を dataclass として受け取る方法

2021/06/06に公開

環境

Python 3.9

結論

json.load()object_hook というオプション引数を指定してあげれば簡単です。

holidays.json
[
  {
    "name": "元日",
    "date": "2021-01-01"
  },
  {
    "name": "成人の日",
    "date": "2021-01-11"
  }
]
data.py
from datetime import date
from dataclasses import dataclass


@dataclass
class Holiday:
    name: str
    date: date
decoder.py
import datetime

from data import Holiday


def decode_holiday(data: dict) -> Holiday:
    name = data['name']

    tmp_date = datetime.datetime.strptime(data['date'], '%Y-%m-%d')
    date = datetime.date(tmp_date.year, tmp_date.month, tmp_date.day)
    return Holiday(name=name, date=date)
main.py
import json

from data import Holiday
from decoder import decode_holiday


def print_holidays():
    holidays_file = open('holidays.json', 'r')
    holidays: [Holiday] = json.load(holidays_file, object_hook=decode_holiday)
    print(holidays)


if __name__ == '__main__':
    print_holidays()
    # [Holiday(name='元日', date=datetime.date(2021, 1, 1)), Holiday(name='成人の日', date=datetime.date(2021, 1, 11))]

追記

pydantic というライブラリを使うと、自動で date 型への変換もやってくれます。
※ Twitter で yu-ichiro さん に教えていただきました

pip install pydantic
data.py
from datetime import date

from pydantic.dataclasses import dataclass


@dataclass
class Holiday:
    name: str
    date: date
main.py
from typing import List

import pydantic

from data import Holiday


def print_holidays():
    holidays: List[Holiday] = pydantic.parse_file_as(List[Holiday], 'holidays.json')
    print(holidays)


if __name__ == '__main__':
    print_holidays()
    # [Holiday(name='元日', date=datetime.date(2021, 1, 1)), Holiday(name='成人の日', date=datetime.date(2021, 1, 11))]

参考

Discussion