Десериализация вложенных полей в marshmallow
Я использую API, который возвращает что-то вроде:
{'name': 'foo', 'start': {'date': '2016-06-19', 'time': '18:00'}}
и я хочу десеариализовать его с помощью зефира, чтобы получить только имя и дату начала, поэтому желаемый результат будет следующим:
{'name': 'foo', 'date': '2016-06-19'}
но я не нашел никакого способа получить дату, это то, что я пробовал:
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)
2 ответов
вам нужно будет создать NestedSchema
для вложенного словаря и перезапишитеload
метод добавления вложенного поля к родительскому. Указать так 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
и настройка экземпляра схемы следующим образом:
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'}
вы всегда можете настроить на свой вкус.
то, что вы описываете может быть достигнуто путем преобразование* ваши входные данные в предварительная обработка* шаг. Хотя принятый ответ выглядит так, как будто он это сделает,зефир имеет встроенные декораторы чтобы позволить вам сделать это таким образом, что я думаю, еще яснее:
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()
date = fields.Str(load_from='start.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
*преобразование и предварительно обработать термины искусства в области объектного моделирования и обработки данных. Я осмелел, потому что зная это может помочь людям, которые читают этот вопрос успешно Google для ответов на вопросы.