Python中類的JSON序列化

__HelloWorld__發表於2018-01-11

這肯定是個老生常談的問題,在此記錄下。

在Python中,當在我們使用sqlalchemy.orm來對資料庫物件進行存取,並將這些資料展現到前臺頁面時,我們就面臨如何將Python中的類物件進行JSON序列化。

簡單起見,我們從程式碼說起:

首先,我們定義一個使用者類,用以儲存使用者資訊

class User(object):
    def __init__(self, id, name, password):
        self.__id = id
        self.__name = name
        self.__password = password

    def __repr__(self):
        return "id is %s, name is %s, password is %s" % (self.__id, self.__name, self.__password)

    def get_name(self):
        return self.__name

    def get_password(self):
        return self.__password

    def get_id(self):
        return self.__id

例項化一個使用者物件user1,並直接進行JSON序列化dumps操作

    user1 = User(1, 'test', 'password')
    print(user1)
    # 直接序列化

    print(json.dumps(user1))

得到報錯資訊:

TypeError: Object of type ‘User’ is not JSON serializable

User物件無法直接序列化,看下dumps方法的定義:

def dumps(obj, *, skipkeys=False, ensure_ascii=True, check_circular=True,
        allow_nan=True, cls=None, indent=None, separators=None,
        default=None, sort_keys=False, **kw):

注意,default引數定義如下:

default(obj) is a function that should return a serializable version
of obj or raise TypeError. The default simply raises TypeError.

因此,我們給User物件指定一個序列化方法:

def user_to_str(user):
    return {'id': user.get_id(), 'name': user.get_name(), 'password': user.get_password()}

重新執行dumps方法,我們得到如下結果:

{“id”: 1, “name”: “test”, “password”: “password”}

當然,在Python中_dict_是一個特殊的屬性,其包含了類的所有屬性,因此,我們還可以給User物件指定如下引數

json.dumps(user1, default=lambda obj: obj.dict)

重新執行,我們得到如下結果:

{“_User__id”: 1, “_User__name”: “test”, “_User__password”: “password”}

假設我們重新定義一個Teacher類,如下:

class Teacher(object):
    __slots__ = ('address', 'grade')

    def __repr__(self):
        address = None
        grade = None
        if hasattr(self, 'address'):
            address = self.address
        if hasattr(self, 'grade'):
            grade = self.grade
        return "address is %s, grade is %s" % (address, grade)

注意,與User類略有不同的是,我們通過_slots_內建屬性限制了物件Teacher只具備addressgrade屬性,我們重新執行方法

json.dumps(teacher, default=lambda obj: obj.dict)

得到報錯資訊:

AttributeError: ‘Teacher’ object has no attribute ‘dict

使用_slots_限制的類不具備_dict_屬性,因此,我們還需要自定實現Teacher類的JSON序列化方法

def teacher_to_str(teacher):
    address = ''
    grade = ''
    if hasattr(teacher, 'address'):
        address = teacher.address
    if hasattr(teacher, 'grade'):
        grade = teacher.grade
    return {'address': address, 'grade': grade}

相關文章