2016-06-19 9 views
6

Ich raubend eine API, die so etwas wie zurückgibt:Deserialize verschachtelte Felder in Eibisch

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

Und ich mag es desearialize mit Eibisch nur den Namen zu erhalten und das Startdatum, so dass das gewünschte Ergebnis wäre die folgenden:

{'name': 'foo', 'date': '2016-06-19'} 

Aber ich habe keine Möglichkeit bekommen das Datum gefunden, das, was ich habe versucht:

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) 

Antwort

4

Sie müssen NestedSchema für das verschachtelte Wörterbuch erstellen und die Methode load Ihres übergeordneten Schemas überschreiben, um das verschachtelte Feld an den übergeordneten Knoten anzuhängen. Geben Sie ein only Attribut so das Nested Feld nicht alle seine Einzelteile holen:

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 

Und die Einrichtung Ihr Schema Instanz wie folgt:

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

Sie kann immer Feinabstimmung nach Ihrem Geschmack.

+0

Sie können die Geschichte auch kurz mit lambdas schneiden, http://marshmallow.readthedocs.io/en/latest/custom_fields.html#function-fields, was in etwa so: 'date = fields.Function (load_from = ' start ', load_only = True, deserialize = Lambda Start: start [' Datum ']) '. –

6

Was Sie beschreiben, kann durch Transformation * Ihre Eingangsdaten in einem Vorverarbeitung * Schritt erreicht werden. Während die akzeptierte Antwort aussieht wird es das tun, Marshmallow has built-in decorators, damit Sie dies in einer Art und Weise zu erreichen, die ich denke, ist noch deutlicher:

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 

* verwandeln und Vorprozess Bezug auf Kunst sind in die Domäne der Objektmodellierung und Datenverarbeitung. Ich habe sie fett geschrieben, denn wenn sie diese Informationen kennen, könnte dies Leuten helfen, die diese Frage erfolgreich durchlesen, um Antworten auf verwandte Fragen zu erhalten.

+2

Ich denke, dass 'load_from = 'start.date' ist hier falsch –