2022年2月16日水曜日

Python の marshmallow を使って JSON からオブジェクトにデシリアライズする方法

Python の marshmallow を使って JSON からオブジェクトにデシリアライズする方法

概要

例えば JSON としてレスポンスを取得してその結果を Python のオブジェクトとしてデシリアライズしたい場合があると思います

そんな場合は marshmallow を使うと簡単に実現できます

環境

  • macOS 11.6.3
  • Python 3.9.10
  • marshmallow

準備

  • pipenv install marshmallow

サンプルコード

ポイントを後述で紹介します
resp が変換対象の JSON ですがこの JSON の構造に合わせてスキーマクラスや変換用のクラスの定義も変換する必要があります

from dataclasses import dataclass
from marshmallow import Schema, fields, post_load


@dataclass
class User():

    name: str
    age: int


@dataclass
class Users():

    users: list


class UserSchema(Schema):

    name = fields.Str()
    age = fields.Int()

    @post_load
    def make_user(self, data, **kwargs):
        return User(**data)


class UsersSchema(Schema):

    users = fields.List(fields.Nested(UserSchema))

    @post_load
    def make_users(self, data, **kwargs):
        return Users(**data)


if __name__ == "__main__":
    resp = {
        "users": [
            {
                "name": "hawk",
                "age": 10
            },
            {
                "name": "snowlog",
                "age": 20
            }
        ]
    }
    schema = UsersSchema()
    users = schema.load(resp)
    for user in users.users:
        print(user.name)
        print(user.age)

ポイント

marshmallow の Schema クラスを継承したスキーマを作成します
スキーマは load や dump を使うことでシリアライズやデシリアライズができるようになります
今回はデシリアライズするので load を使って JSON -> Python オブジェクトの変換を行います

変換先の Python オブジェクトのクラスは普通に Python のクラスと定義します
今回は dataclass を使っていますが dataclass じゃなくて OK です

最大のポイントはスキーマ側で post_load を使ってデシリアライズ時に data を定義したクラスで変換してから return する点です
これをしないと JSON -> dict という感じで Python オブジェクトに変換されず dict として受け取れてしまうので注意が必要です
逆に dict にしたい場合は post_load は不要です

最後に

Python のシリアライズと言えば marshmallow なので覚えておきましょう
基本的な使い方さえわからばデータベースからの変換やRedisからの変換も簡単にできると思います

0 件のコメント:

コメントを投稿