【ヒント】Python ミキシン - JsonSerializableMixin

By khoanc, at: 2025年3月1日17:40

Estimated Reading Time: __READING_TIME__ minutes

[TIPS] Python Mixins - JsonSerializableMixin
[TIPS] Python Mixins - JsonSerializableMixin

 

1. Basic JsonSerializableMixin

 

全ての属性をJSONに迅速にダンプします

 

import json

class JsonSerializableMixin:
    def to_json(self):
        return json.dumps(vars(self))

class Product(JsonSerializableMixin):
    def __init__(self, name, price):
        self.name = name
        self.price = price

print(Product("Laptop", 1200).to_json())
# {"name": "Laptop", "price": 1200}

 

=> 高速でシンプル

 

しかし、入れ子になったオブジェクトや特殊な型は処理できません。

 

2. カスタムフィールドホワイトリスト

 

特定のフィールド(__json_fields__)のみを含めます

 

import json

class JsonWhitelistMixin:
    __json_fields__ = []

    def to_json(self):
        data = {field: getattr(self, field) for field in self.__json_fields__ if hasattr(self, field)}
        return json.dumps(data)


class User(JsonWhitelistMixin):
    __json_fields__ = ["username", "email"]

    def __init__(self, username, email, password):
        self.username = username
        self.email = email
        self.password = password  # 除外


print(User("Joe", "[email protected]", "amazing Python team").to_json())
# {"username": "Joe", "email": "[email protected]"}

 

=> セキュリティに最適(パスワード、トークンなどの非表示)。

 

3. ネストされたオブジェクトのサポート

 

to_json()またはto_dict()を使用して、リスト、辞書、その他のオブジェクトを処理します

 

import json

class JsonNestedMixin:
    def to_dict(self):
        def convert(obj):
            if isinstance(obj, list):
                return [convert(i) for i in obj]
            if isinstance(obj, dict):
                return {k: convert(v) for k, v in obj.items()}
            if hasattr(obj, "to_dict"):
                return obj.to_dict()
            return obj

        return {k: convert(v) for k, v in vars(self).items()}

    def to_json(self):
        return json.dumps(self.to_dict())


class Address(JsonNestedMixin):
    def __init__(self, city, country):
        self.city = city
        self.country = country


class Person(JsonNestedMixin):
    def __init__(self, name, addresses):
        self.name = name
        self.addresses = addresses


p = Person("Glinteco", [Address("Hanoi", "Vietnam"), Address("Melbourne", "Australia")])
print(p.to_json())
# {"name": "Glinteco", "addresses": [{"city": "Hanoi", "country": "Vietnam"}, {"city": "Melbourne", "country": "Australia"}]}

 

=> 実際のオブジェクトグラフを処理します。

 

4. JSONではない型のカスタムエンコーダ

 

datetime、Decimal、その他の特殊な型をサポートします

 

import json, datetime, decimal


class CustomEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, datetime.datetime):
            return obj.isoformat()
        if isinstance(obj, decimal.Decimal):
            return float(obj)
        return super().default(obj)


class JsonCustomEncoderMixin:
    def to_json(self):
        return json.dumps(vars(self), cls=CustomEncoder)


class Invoice(JsonCustomEncoderMixin):
    def __init__(self, amount, issued_at):
        self.amount = decimal.Decimal(amount)
        self.issued_at = issued_at


print(Invoice("1200.50", datetime.datetime(2025, 9, 6, 14, 30)).to_json())
# {"amount": 1200.5, "issued_at": "2025-09-06T14:30:00"}

 

=> 通常のjson.dumpsを壊してしまうような現実世界のデータ型でも機能します。

 

Tag list:

Subscribe

Subscribe to our newsletter and never miss out lastest news.