2016-06-19 4 views
6

Я потребляющие API, который возвращает что-то вроде:десериализации вложенные поля в зефире

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

И я хочу desearialize его с зефиром, чтобы получить только имя и дату начала, так что желаемый результат будет следующее:

{'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) 

ответ

4

Вам нужно будет создать 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 

и настройка экземпляра схемы следующим образом:

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'} 

Вы всегда можете выполнить точную настройку на свой вкус.

+0

Вы также можете сократить историю с помощью lambdas, http://marshmallow.readthedocs.io/en/latest/custom_fields.html#function-fields, выполнив что-то вроде этого: 'date = fields.Function (load_from = ' start ', load_only = True, deserialize = lambda start: start [' date ']) '. –

6

что вы описываете может быть достигнут путем преобразующим * ваших входных данных в предварительной обработке * шага. Хотя принятый ответ выглядит, как он будет делать, Marshmallow has built-in decorators, чтобы позволить вам сделать это таким образом, что я думаю, это еще яснее:

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 для ответов на связанные вопросы.

+2

Я думаю, что здесь 'load_from = 'start.date'' неверно –

Смежные вопросы