使用Python棉花糖

时间:2020-05-07 14:52:08

标签: python python-3.x marshmallow

我正在尝试使用棉花糖模式序列化python对象。下面是我为数据定义的架构。

from marshmallow import Schema, fields

class User:

    def __init__(self, name = None, age = None, is_active = None, details = None):
        self.name = name
        self.age = age
        self.is_active = is_active
        self.details = details

class UserSchema(Schema):
    name = fields.Str()
    age = fields.Int()
    is_active = fields.Bool()
    details = fields.Dict()

输入将以字典格式,所有值将为字符串。

user_data = {"name":"xyz", "age":"20", "is_active": 'true',"details":"{'key1':'val1', 'key2':'val2'}"}

当我尝试运行以下代码段时, age is_active 的值已转换为各自的数据类型,但详细信息保持不变。

user_schema = UserSchema()
user_dump_data = user_schema.dump(user_data)
print(user_dump_data)

输出:

{'name': 'xyz', 'is_active': True, 'details': "{'key1':'val1', 'key2':'val2'}", 'age': 20}

我需要将输入数据序列化为我在架构中定义的相应数据类型。我做错了什么吗?谁能指导我如何使用棉花糖实现这一目标?

我正在使用

python 3.6
marshmallow 3.5.1

修改

上述输入数据是从HBase获取的。默认情况下,HBase将其所有值存储为字节,并以字节返回。下面是我从HBase获得的格式

{b'name': b'xyz', b'age': b'20', b'is_active': b'true', b'details': b"{'key1':'val1', 'key2':'val2'}"}

然后我解码该词典并将其传递给我的UserSchema,以序列化它以在Web API中使用。

2 个答案:

答案 0 :(得分:1)

您混淆了序列化(转储)和反序列化(加载)。

转储从对象形式到json可序列化的基本python类型(使用Schema.dump)或json字符串(使用Schema.dumps)。加载是相反的操作。

通常,您的API从外界加载(并验证)数据,并将您的对象(未经验证)转储到外界。

如果输入数据是此数据,并且想要将其加载到对象中,则需要使用load,而不是dump

user_data = {"name":"xyz", "age":"20", "is_active": 'true',"details":"{'key1':'val1', 'key2':'val2'}"}
user_loaded_data = user_schema.load(user_data)
user = User(**user_loaded_data)

除非您这样做,否则将被另一个问题困扰。 DictField期望数据为dict,而不是str。您需要输入

user_data = {"name":"xyz", "age":"20", "is_active": 'true',"details": {'key1':'val1', 'key2':'val2'}}

答案 1 :(得分:1)

正如Jérôme所述,您将序列化(转储)与反序列化(加载)混为一谈。根据您的要求,应按照建议使用Schema.load

因为,所有输入值都应为字符串类型。您可以使用pre_load注册用于预处理数据的方法,如下所示:

from marshmallow import Schema, fields, pre_load

class UserSchema(Schema):
    name = fields.Str()
    age = fields.Int()
    is_active = fields.Bool()
    details = fields.Dict()

    @pre_load
    def pre_process_details(self, data, **kwarg):
        data['details'] = eval(data['details'])
        return data

user_data = {"name":"xyz", "age":"20", "is_active": 'true',"details":"{'key1':'val1', 'key2':'val2'}"}

user_schema = UserSchema()
user_loaded_data = user_schema.load(user_data)
print(user_loaded_data)

在这里,pre_process_details会将字符串类型转换为字典以进行正确的反序列化。