概要
例えば JSON としてレスポンスを取得してその結果を Python のオブジェクトとしてデシリアライズしたい場合があると思います
そんな場合は marshmallow を使うと簡単に実現できます
環境
- macOS 11.6.3
- Python 3.9.10
- marshmallow
準備
- pipenv install marshmallow
サンプルコード
ポイントを後述で紹介します
resp が変換対象の JSON ですがこの JSON の構造に合わせてスキーマクラスや変換用のクラスの定義も変換する必要があります
- vim app.py
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 件のコメント:
コメントを投稿