🙌

Pythonのリクエストデータを動的にシリアライズする方法

2024/09/09に公開

はじめに

pythonのweb開発において、リクエストパラメータなどのデータを動的にシリアライズ(変換処理)したい場面があると思います。
そういった時は、シリアライズ専用の関数を予め定義しておくと便利です。

実際のコード

pythonのdataclassesモジュールを使用します。

converter.py
from dataclasses import dataclass, asdict
from typing import Callable
# 以下は独自に定義した関数
from utils import convert_to_datetime, to_uuid
from data_models.params import SampleDataParams

def serialize(params: SampleDataParams) -> dict:
    """シリアライズする
    Args: 
        SampleDataParams: @dataclassで定義したリクエストオブジェクト
    Returns:
        dict: シリアライズしたデータ
    """
    dict_data = asdict(params)
    model_dict = {}

    for config in MAP_CONFIGS:
        model_dict.update(config.convert(dict_data))

    return model_dict

こちらのserialize関数は、リクエストオブジェクトに対してdataclassesモジュールのasdict関数を使って、一旦dict型に変換してから繰り返し処理の中でMAP_CONFIGS定数のconvert関数で変換処理を行い、model_dictという空オブジェクトに格納して返却しています。

では、続いてMAP_CONFIGSの定義を見てみます。

MAP_CONFIGS: list[MapConfig] = [
    MapConfig("user_id", converter=to_uuid),
    MapConfig("age"),
    MapConfig("register_time", dist_key=register_datetime, converter=convert_to_datetime)
]

こちらの定義では、リクエストオブジェクトに格納されているデータに対して、MapConfigクラスによってdist_keyで名前空間の変更を行い、converterでUUID型やdatetime型への変換処理を行っています。
次に、MapConfigクラスの定義を見てみます。

@dataclass
class MapConfig:
    src_key: str
    dist_key: str | None = None
    converter: Callable | None = None

    def convert(self, src_data: dict) -> dict:
        value = src_data.get(self.src_key)
        dist_key = self.dist_key or self.src_key

        if value is None or self.converter is None:
            return {dist_key: value}

        return {dist_key: self.converter(value)}

こちらのclass定義では、MapConfigクラスにconvertメソッドを定義し、converterを再帰的に呼び出して変換処理を行っています。
これで、後はserialize関数を呼び出せばデータを動的にシリアライズ出来るようになります。

from converter import serialize

obj = serialize(SampleDataParams())

"""obj
{
    "user_id": UUID(~~~~~),
    "age": "20", 
    "register_datetime": datetime(2024, 9, 9, 20, 55, 28)
}
"""

終わりに

以上、簡単ではありますが、pythonにおけるデータの動的シリアライズに関する記事でした。
これからもちょくちょく実務で学んだことをアウトプットしていこうと思いますのでよろしくお願いします!

Discussion