反序列化marshmallow中的嵌套字段

cam*_*aya 8 python preprocessor transformation marshmallow

我正在使用返回类似以下内容的API:

{'name': 'foo', 'start': {'date': '2016-06-19', 'time': '18:00'}}
Run Code Online (Sandbox Code Playgroud)

我想用棉花糖去除它,只获得名称和开始日期,所以期望的结果如下:

{'name': 'foo', 'date': '2016-06-19'}
Run Code Online (Sandbox Code Playgroud)

但我没有找到任何方法来获取日期,这是我尝试过的:

from marshmallow import Schema, fields, pprint

event = {'name': 'foo', 'start': {'date': '2016-06-19', 'time': '18:00'}}
class EventSchema(Schema):
    name = fields.Str()
    date = fields.Str(load_from='start.date')


schema = EventSchema()
result = schema.load(event)
pprint(result.data)
Run Code Online (Sandbox Code Playgroud)

Ste*_*tew 14

您所描述的内容可以通过在预处理*步骤中转换*您的输入数据来完成.虽然接受的答案看起来会这样做,但Marshmallow有内置的装饰器,让你以我认为更清晰的方式实现这一点:

from marshmallow import Schema, pre_load, fields, pprint

event = {'name': 'foo', 'start': {'date': '2016-06-19', 'time': '18:00'}}
expected = {'name': 'foo', 'date': '2016-06-19'}


class EventSchema(Schema):
    name = fields.Str()
    # Marshmallow 2
    date = fields.Str(load_from='date')
    # Marshmallow 3
    date = fields.Str(data_key='date')

    @pre_load
    def move_date(self, data):
        """This will alter the data passed to ``load()`` before Marshmallow
        attempts deserialization.
        """
        start = data.pop('start')
        data['date'] = start['date']
        return data

schema = EventSchema()
result = schema.load(event)
pprint(result.data)

assert result.data == expected
Run Code Online (Sandbox Code Playgroud)

*变换预处理是对象建模和数据处理领域的艺术术语.我加粗了他们,因为知道这些可能会帮助那些成功阅读这个问题的人们获得相关问题的答案.

  • 我认为`load_from ='start.date'`在这里是不正确的 (3认同)
  • 从3.0.0b8版本开始,`load_from`和`dump_to`被替换为`data_key`参数:https://marshmallow.readthedocs.io/en/dev/api_reference.html?highlight=load_from#module -棉花糖领域 (2认同)

Mos*_*oye 7

您将需要NestedSchema为嵌套字典创建一个,并覆盖您的父模式的load方法以将嵌套字段附加到父级.指定一个only属性,以便该Nested字段不会获取其所有项:

class DateTimeSchema(Schema):
    date = fields.Str()
    time = fields.Str()


class EventSchema(Schema):
    name = fields.Str()
    date = fields.Nested(DateTimeSchema, load_from='start', only='date')

    def load(self, *args, special=None):
        _partial = super(EventSchema, self).load(*args)

        # Move special field from Nest to Parent
        if special is not None and special in _partial.data:
            _partial.data[special]  = _partial.data[special].get(special)
        return _partial
Run Code Online (Sandbox Code Playgroud)

并设置您的架构实例,如下所示:

event = {'name': 'foo', 'start': {'date': '2016-06-19', 'time': '18:00'}}

schema, special_field = EventSchema(), 'date'
result = schema.load(event, special=special_field)
pprint(result.data)
# {'name': 'foo', 'date': '2016-06-19'}
Run Code Online (Sandbox Code Playgroud)

您可以随时根据自己的口味进行微调.