class User: def __init__(self, name, age, address): self.name = name self.age = age self.address = address class Address: def __init__(self, city, street, pin): self.city = city self.street = street self.pin = pin address = Address("Tokyo", "Shinjuku", 1214) user = User("uran", 26, address)
このUserクラスインスタンス user を JSONシリアライズしたい。
もっともシンプルな方法
import json str = json.dumps(user, default=lambda o:o.__dict__, indent=3) print(str)
{ "name": "uran", "age": 26, "address": { "city": "Tokyo", "street": "Shinjuku", "pin": 1214 } }
default=lambda o:o.__dict__ は、つまり以下メソッドを宣言して渡すことと同じ
def toJson(o): return o.__dict__
str = json.dumps(user, default=toJson, indent=3)
もう1つ、json.JSONEncoder を継承して行う方法
import json from json import JSONEncoder
JSONEncoder 継承するクラスを用意
class MyEncoder(JSONEncoder): def default(self, o): return o.__dict__
そのまま実行すると
str = MyEncoder().(user) print(str)
{"name": "uran", "age": 26, "address": {"city": "Tokyo", "street": "Shinjuku", "pin": 1214}}
とインデントはデフォルトで無いので、MyEncoder 生成時に指定しなければならない
str = MyEncoder(indent=3).(user)
ただし、これら、__dict__ を使ったJSONシリアライズは、
軽量・高速化を目的とした__slots__ を宣言しているクラスでは使えません。
AttributeError: 'User' object has no attribute '__dict__'
になり属性を __dict__.['attributeName'] という参照ができなくなります。
__dict__ は内部で直接参照しにいくみたいです。
class User: __slots__ = ['name', 'age', 'address'] def __init__(self, name, age, address): self.name = name self.age = age self.address = address