反序列化棉花糖中的嵌套字段
Deserialize nested fields in marshmallow
我正在消耗 API returns 类似的东西:
{'name': 'foo', 'start': {'date': '2016-06-19', 'time': '18:00'}}
我想用 marshmallow 对其进行反序列化以仅获取名称和开始日期,因此所需的结果如下:
{'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)
您需要为嵌套字典创建一个 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'}
您可以随时根据自己的口味进行微调。
您所描述的可以通过在预处理*步骤中转换*您的输入数据来实现。虽然接受的答案看起来会这样做,但 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()
# 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
* transform 和 pre-process 是对象建模和数据处理领域的术语。我将它们加粗是因为了解这些可能有助于成功阅读此问题的人 Google 获得相关问题的答案。
棉花糖 3 有 Pluck
:
class DateTimeSchema(Schema):
date = fields.Str()
time = fields.Str()
class EventSchema(Schema):
name = fields.Str()
date = fields.Pluck(DateTimeSchema, 'date')
看到前面的答案有多么复杂,我想提供一个非常简单的解决方案(使用fields.Function
):
from marshmallow import Schema, fields
class EventSchema(Schema):
name = fields.Str()
date = fields.Function(data_key='start',
deserialize=lambda start: start['date'])
schema = EventSchema()
event = {'name': 'foo', 'start': {'date': '2016-06-19', 'time': '18:00'}}
result = schema.load(event)
print(result)
结果符合预期:{'name': 'foo', 'date': '2016-06-19'}
。
这适用于 marshmallow
的第 3 版。
我正在消耗 API returns 类似的东西:
{'name': 'foo', 'start': {'date': '2016-06-19', 'time': '18:00'}}
我想用 marshmallow 对其进行反序列化以仅获取名称和开始日期,因此所需的结果如下:
{'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)
您需要为嵌套字典创建一个 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'}
您可以随时根据自己的口味进行微调。
您所描述的可以通过在预处理*步骤中转换*您的输入数据来实现。虽然接受的答案看起来会这样做,但 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()
# 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
* transform 和 pre-process 是对象建模和数据处理领域的术语。我将它们加粗是因为了解这些可能有助于成功阅读此问题的人 Google 获得相关问题的答案。
棉花糖 3 有 Pluck
:
class DateTimeSchema(Schema):
date = fields.Str()
time = fields.Str()
class EventSchema(Schema):
name = fields.Str()
date = fields.Pluck(DateTimeSchema, 'date')
看到前面的答案有多么复杂,我想提供一个非常简单的解决方案(使用fields.Function
):
from marshmallow import Schema, fields
class EventSchema(Schema):
name = fields.Str()
date = fields.Function(data_key='start',
deserialize=lambda start: start['date'])
schema = EventSchema()
event = {'name': 'foo', 'start': {'date': '2016-06-19', 'time': '18:00'}}
result = schema.load(event)
print(result)
结果符合预期:{'name': 'foo', 'date': '2016-06-19'}
。
这适用于 marshmallow
的第 3 版。