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", "joe@glinteco.com", "amazing Python team").to_json())
# {"username": "Joe", "email": "joe@glinteco.com"}

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

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を壊してしまうような現実世界のデータ型でも機能します。